diff options
Diffstat (limited to 'test/dt_arith.c')
-rw-r--r-- | test/dt_arith.c | 1062 |
1 files changed, 967 insertions, 95 deletions
diff --git a/test/dt_arith.c b/test/dt_arith.c index 9870ea1..3c21896 100644 --- a/test/dt_arith.c +++ b/test/dt_arith.c @@ -62,6 +62,7 @@ typedef enum dtype_t { INT_ULONG, INT_LLONG, INT_ULLONG, + FLT_FLOAT16, FLT_FLOAT, FLT_DOUBLE, FLT_LDOUBLE, @@ -442,6 +443,9 @@ reset_hdf5(void) SET_ALIGNMENT(FLOAT, H5_SIZEOF_FLOAT); SET_ALIGNMENT(DOUBLE, H5_SIZEOF_DOUBLE); SET_ALIGNMENT(LDOUBLE, H5_SIZEOF_LONG_DOUBLE); +#ifdef H5_HAVE__FLOAT16 + SET_ALIGNMENT(FLOAT16, H5_SIZEOF__FLOAT16); +#endif #endif } @@ -575,13 +579,16 @@ expt_handle(H5T_conv_except_t except_type, hid_t H5_ATTR_UNUSED src_id, hid_t H5 { signed char fill_value1 = 7; int fill_value2 = 13; + short fill_value3 = 25; if (except_type == H5T_CONV_EXCEPT_RANGE_HI || except_type == H5T_CONV_EXCEPT_RANGE_LOW || except_type == H5T_CONV_EXCEPT_TRUNCATE) { - if (*(bool *)user_data) + if (*(int *)user_data == 0) + *(int *)dst_buf = fill_value2; + else if (*(int *)user_data == 1) *(signed char *)dst_buf = fill_value1; else - *(int *)dst_buf = fill_value2; + *(short *)dst_buf = fill_value3; } /* end if */ return H5T_CONV_HANDLED; @@ -612,19 +619,34 @@ static int test_particular_fp_integer(void) { hid_t dxpl_id; - bool flag; + int flag; double src_d = (double)SCHAR_MAX; signed char dst_c; - unsigned char *buf1 = NULL, *buf2 = NULL; - unsigned char *saved_buf1 = NULL, *saved_buf2 = NULL; - size_t src_size1, src_size2; - size_t dst_size1, dst_size2; - float src_f = (float)INT_MAX; - int dst_i; - int fill_value = 13; + unsigned char *buf1 = NULL; + unsigned char *saved_buf1 = NULL; + size_t src_size1; + size_t dst_size1; int endian; /*endianness */ unsigned int fails_this_test = 0; size_t j; +#ifdef H5_WANT_DCONV_EXCEPTION + unsigned char *buf2 = NULL; + unsigned char *saved_buf2 = NULL; + size_t src_size2; + size_t dst_size2; + float src_f = (float)INT_MAX; + int fill_value = 13; + int dst_i; +#ifdef H5_HAVE__FLOAT16 + unsigned char *buf3 = NULL; + unsigned char *saved_buf3 = NULL; + H5__Float16 src_half = (H5__Float16)SHRT_MAX; + short s_fill_val = 25; + short dst_s; + size_t src_size3; + size_t dst_size3; +#endif +#endif TESTING("hard particular floating number -> integer conversions"); @@ -685,6 +707,8 @@ test_particular_fp_integer(void) printf(" %29d\n", y); } +/* Only run this part of the test if conversion exceptions are enabled */ +#ifdef H5_WANT_DCONV_EXCEPTION /* Test conversion from float (the value is INT_MAX) to int. */ src_size2 = H5Tget_size(H5T_NATIVE_FLOAT); dst_size2 = H5Tget_size(H5T_NATIVE_INT); @@ -729,6 +753,53 @@ test_particular_fp_integer(void) printf(" %29d\n", y); } +#ifdef H5_HAVE__FLOAT16 + /* Test conversion from _Float16 (the value is INT_MAX) to int. */ + src_size3 = H5Tget_size(H5T_NATIVE_FLOAT16); + dst_size3 = H5Tget_size(H5T_NATIVE_SHORT); + buf3 = (unsigned char *)calloc((size_t)1, (size_t)MAX(src_size3, dst_size3)); + saved_buf3 = (unsigned char *)calloc((size_t)1, (size_t)MAX(src_size3, dst_size3)); + memcpy(buf3, &src_half, src_size3); + memcpy(saved_buf3, &src_half, src_size3); + + /* Register exception handling function and signal the destination is "short". */ + flag = 2; + + /* Do conversion */ + if (H5Tconvert(H5T_NATIVE_FLOAT16, H5T_NATIVE_SHORT, (size_t)1, buf3, NULL, dxpl_id) < 0) { + H5_FAILED(); + printf("Can't convert data\n"); + goto error; + } + + memcpy(&dst_s, buf3, dst_size3); + + /* Print errors */ + if (dst_s != s_fill_val) { + H5__Float16 x; + short y; + + if (0 == fails_this_test++) + H5_FAILED(); + + printf(" test _Float16 to short:\n"); + printf(" src = "); + for (j = 0; j < src_size3; j++) + printf(" %02x", saved_buf3[ENDIAN(src_size3, j, endian)]); + + memcpy(&x, saved_buf3, src_size3); + printf(" %29.20e\n", (double)x); + + printf(" dst = "); + for (j = 0; j < dst_size3; j++) + printf(" %02x", buf3[ENDIAN(dst_size3, j, endian)]); + + memcpy(&y, buf3, dst_size3); + printf(" %29d\n", (int)y); + } +#endif +#endif + if (fails_this_test) goto error; @@ -740,12 +811,27 @@ test_particular_fp_integer(void) if (buf1) free(buf1); + +#ifdef H5_WANT_DCONV_EXCEPTION if (buf2) free(buf2); +#ifdef H5_HAVE__FLOAT16 + if (buf3) + free(buf3); +#endif +#endif + if (saved_buf1) free(saved_buf1); + +#ifdef H5_WANT_DCONV_EXCEPTION if (saved_buf2) free(saved_buf2); +#ifdef H5_HAVE__FLOAT16 + if (saved_buf3) + free(saved_buf3); +#endif +#endif PASSED(); return 0; @@ -759,12 +845,27 @@ error: H5E_END_TRY if (buf1) free(buf1); + +#ifdef H5_WANT_DCONV_EXCEPTION if (buf2) free(buf2); +#ifdef H5_HAVE__FLOAT16 + if (buf3) + free(buf3); +#endif +#endif + if (saved_buf1) free(saved_buf1); + +#ifdef H5_WANT_DCONV_EXCEPTION if (saved_buf2) free(saved_buf2); +#ifdef H5_HAVE__FLOAT16 + if (saved_buf3) + free(saved_buf3); +#endif +#endif /* Restore the default error handler (set in h5_reset()) */ h5_restore_err(); @@ -1532,17 +1633,16 @@ error: * Function: test_conv_int_1 * * Purpose: Test conversion of integer values from SRC to DST. - * These types should be any combination of: + * These types should be any combination of: * * H5T_NATIVE_SCHAR H5T_NATIVE_UCHAR - * H5T_NATIVE_SHORT H5T_NATIVE_USHORT - * H5T_NATIVE_INT H5T_NATIVE_UINT - * H5T_NATIVE_LONG H5T_NATIVE_ULONG - * H5T_NATIVE_LLONG H5T_NATIVE_ULLONG + * H5T_NATIVE_SHORT H5T_NATIVE_USHORT + * H5T_NATIVE_INT H5T_NATIVE_UINT + * H5T_NATIVE_LONG H5T_NATIVE_ULONG + * H5T_NATIVE_LLONG H5T_NATIVE_ULLONG * * Return: Success: 0 - * - * Failure: number of errors + * Failure: number of errors * *------------------------------------------------------------------------- */ @@ -1783,6 +1883,7 @@ test_conv_int_1(const char *name, hid_t src, hid_t dst) memcpy(aligned, saved + j * sizeof(unsigned long long), sizeof(unsigned long long)); hw_char = (signed char)(*((unsigned long long *)aligned)); break; + case FLT_FLOAT16: case FLT_FLOAT: case FLT_DOUBLE: case FLT_LDOUBLE: @@ -1835,6 +1936,7 @@ test_conv_int_1(const char *name, hid_t src, hid_t dst) memcpy(aligned, saved + j * sizeof(unsigned long long), sizeof(unsigned long long)); hw_uchar = (unsigned char)(*((unsigned long long *)aligned)); break; + case FLT_FLOAT16: case FLT_FLOAT: case FLT_DOUBLE: case FLT_LDOUBLE: @@ -1887,7 +1989,7 @@ test_conv_int_1(const char *name, hid_t src, hid_t dst) memcpy(aligned, saved + j * sizeof(unsigned long long), sizeof(unsigned long long)); hw_short = (short)(*((unsigned long long *)aligned)); break; - + case FLT_FLOAT16: case FLT_FLOAT: case FLT_DOUBLE: case FLT_LDOUBLE: @@ -1940,6 +2042,7 @@ test_conv_int_1(const char *name, hid_t src, hid_t dst) memcpy(aligned, saved + j * sizeof(unsigned long long), sizeof(unsigned long long)); hw_ushort = (unsigned short)(*((unsigned long long *)aligned)); break; + case FLT_FLOAT16: case FLT_FLOAT: case FLT_DOUBLE: case FLT_LDOUBLE: @@ -1992,6 +2095,7 @@ test_conv_int_1(const char *name, hid_t src, hid_t dst) memcpy(aligned, saved + j * sizeof(unsigned long long), sizeof(unsigned long long)); hw_int = (int)(*((unsigned long long *)aligned)); break; + case FLT_FLOAT16: case FLT_FLOAT: case FLT_DOUBLE: case FLT_LDOUBLE: @@ -2044,6 +2148,7 @@ test_conv_int_1(const char *name, hid_t src, hid_t dst) memcpy(aligned, saved + j * sizeof(unsigned long long), sizeof(unsigned long long)); hw_uint = (unsigned int)(*((unsigned long long *)aligned)); break; + case FLT_FLOAT16: case FLT_FLOAT: case FLT_DOUBLE: case FLT_LDOUBLE: @@ -2096,6 +2201,7 @@ test_conv_int_1(const char *name, hid_t src, hid_t dst) memcpy(aligned, saved + j * sizeof(unsigned long long), sizeof(unsigned long long)); hw_long = (long int)(*((unsigned long long *)aligned)); break; + case FLT_FLOAT16: case FLT_FLOAT: case FLT_DOUBLE: case FLT_LDOUBLE: @@ -2148,6 +2254,7 @@ test_conv_int_1(const char *name, hid_t src, hid_t dst) memcpy(aligned, saved + j * sizeof(unsigned long long), sizeof(unsigned long long)); hw_ulong = (unsigned long)(*((unsigned long long *)aligned)); break; + case FLT_FLOAT16: case FLT_FLOAT: case FLT_DOUBLE: case FLT_LDOUBLE: @@ -2200,6 +2307,7 @@ test_conv_int_1(const char *name, hid_t src, hid_t dst) memcpy(aligned, saved + j * sizeof(unsigned long long), sizeof(unsigned long long)); hw_llong = (long long)(*((unsigned long long *)aligned)); break; + case FLT_FLOAT16: case FLT_FLOAT: case FLT_DOUBLE: case FLT_LDOUBLE: @@ -2252,6 +2360,7 @@ test_conv_int_1(const char *name, hid_t src, hid_t dst) memcpy(aligned, saved + j * sizeof(unsigned long long), sizeof(unsigned long long)); hw_ullong = (unsigned long long)(*((unsigned long long *)aligned)); break; + case FLT_FLOAT16: case FLT_FLOAT: case FLT_DOUBLE: case FLT_LDOUBLE: @@ -2434,6 +2543,7 @@ test_conv_int_1(const char *name, hid_t src, hid_t dst) memcpy(aligned, saved + j * sizeof(unsigned long long), sizeof(unsigned long long)); fprintf(stdout, " %29llu\n", *((unsigned long long *)aligned)); break; + case FLT_FLOAT16: case FLT_FLOAT: case FLT_DOUBLE: case FLT_LDOUBLE: @@ -2488,6 +2598,7 @@ test_conv_int_1(const char *name, hid_t src, hid_t dst) memcpy(aligned, buf + j * sizeof(long long), sizeof(unsigned long long)); fprintf(stdout, " %29llu\n", *((unsigned long long *)aligned)); break; + case FLT_FLOAT16: case FLT_FLOAT: case FLT_DOUBLE: case FLT_LDOUBLE: @@ -2532,6 +2643,7 @@ test_conv_int_1(const char *name, hid_t src, hid_t dst) case INT_ULLONG: fprintf(stdout, " %29llu\n", *((unsigned long long *)((void *)hw))); break; + case FLT_FLOAT16: case FLT_FLOAT: case FLT_DOUBLE: case FLT_LDOUBLE: @@ -2664,6 +2776,15 @@ my_isnan(dtype_t type, void *val) retval = isnan(x); #endif } + else if (FLT_FLOAT16 == type) { +#ifdef H5_HAVE__FLOAT16 + H5__Float16 x; + memcpy(&x, val, sizeof(H5__Float16)); + retval = isnan(x); +#else + assert(0 && "Should not reach this point!"); +#endif + } else { return 0; } @@ -2693,6 +2814,16 @@ my_isnan(dtype_t type, void *val) snprintf(s, sizeof(s), "%Lg", x); #endif } + else if (FLT_FLOAT16 == type) { +#ifdef H5_HAVE__FLOAT16 + H5__Float16 x; + + memcpy(&x, val, sizeof(H5__Float16)); + snprintf(s, sizeof(s), "%g", (double)x); +#else + assert(0 && "Should not reach this point!"); +#endif + } else { return 0; } @@ -2735,15 +2866,317 @@ my_isinf(int endian, const unsigned char *val, size_t size, size_t mpos, size_t } /*------------------------------------------------------------------------- + * Function: test_conv_flt_1_hw_conv_from_flt16 + * + * Purpose: Helper function for test_conv_flt_1 to perform conversion + * from _Float16 to another type by casting. Also checks for + * overflow and underflow when the destination type is a type + * with a smaller width than _Float16. + * + * Return: -1 on failure + * 0 on success without overflow or underflow + * 1 on overflow + * 2 on underflow + * + *------------------------------------------------------------------------- + */ +#ifdef H5_HAVE__FLOAT16 +static int +test_conv_flt_1_hw_conv_from_flt16(void *hw_dst, unsigned char *src_buf, size_t idx, dtype_t dst_type) +{ + H5__Float16 aligned; + int ret = 0; + + memcpy(&aligned, src_buf + idx * sizeof(H5__Float16), sizeof(H5__Float16)); + + switch (dst_type) { + case FLT_FLOAT16: + *((H5__Float16 *)hw_dst) = aligned; + break; + case FLT_FLOAT: + *((float *)hw_dst) = (float)aligned; + break; + case FLT_DOUBLE: + *((double *)hw_dst) = (double)aligned; + break; +#if H5_SIZEOF_LONG_DOUBLE != H5_SIZEOF_DOUBLE + case FLT_LDOUBLE: + *((long double *)hw_dst) = (long double)aligned; + break; +#endif + case INT_SCHAR: + case INT_UCHAR: + case INT_SHORT: + case INT_USHORT: + case INT_INT: + case INT_UINT: + case INT_LONG: + case INT_ULONG: + case INT_LLONG: + case INT_ULLONG: + case OTHER: + default: + H5_FAILED(); + printf("invalid destination conversion datatype"); + ret = -1; + goto done; + } + +done: + return ret; +} +#endif + +/*------------------------------------------------------------------------- + * Function: test_conv_flt_1_hw_conv_from_flt + * + * Purpose: Helper function for test_conv_flt_1 to perform conversion + * from float to another type by casting. Also checks for + * overflow and underflow when the destination type is a + * type with a smaller width than float. + * + * Return: -1 on failure + * 0 on success without overflow or underflow + * 1 on overflow + * 2 on underflow + * + *------------------------------------------------------------------------- + */ +static int +test_conv_flt_1_hw_conv_from_flt(void *hw_dst, unsigned char *src_buf, size_t idx, dtype_t dst_type) +{ + float aligned; + int ret = 0; + + memcpy(&aligned, src_buf + idx * sizeof(float), sizeof(float)); + + switch (dst_type) { + case FLT_FLOAT: + *((float *)hw_dst) = aligned; + break; + case FLT_DOUBLE: + *((double *)hw_dst) = (double)aligned; + break; +#if H5_SIZEOF_LONG_DOUBLE != H5_SIZEOF_DOUBLE + case FLT_LDOUBLE: + *((long double *)hw_dst) = (long double)aligned; + break; +#endif + case FLT_FLOAT16: +#ifdef H5_HAVE__FLOAT16 + /* Suppress warning about non-standard floating-point literal suffix */ + H5_GCC_CLANG_DIAG_OFF("pedantic") + + *((H5__Float16 *)hw_dst) = (H5__Float16)aligned; + + /* Check for overflow and underflow */ + if (fabsf(aligned) > (float)FLT16_MAX) + ret = 1; + else if (fabsf(aligned) < (float)FLT16_MIN) + ret = 2; + + H5_GCC_CLANG_DIAG_ON("pedantic") + break; +#endif + case INT_SCHAR: + case INT_UCHAR: + case INT_SHORT: + case INT_USHORT: + case INT_INT: + case INT_UINT: + case INT_LONG: + case INT_ULONG: + case INT_LLONG: + case INT_ULLONG: + case OTHER: + default: + H5_FAILED(); + printf("invalid destination conversion datatype"); + ret = -1; + goto done; + } + +done: + return ret; +} + +/*------------------------------------------------------------------------- + * Function: test_conv_flt_1_hw_conv_from_double + * + * Purpose: Helper function for test_conv_flt_1 to perform conversion + * from double to another type by casting. Also checks for + * overflow and underflow when the destination type is a + * type with a smaller width than double. + * + * Return: -1 on failure + * 0 on success without overflow or underflow + * 1 on overflow + * 2 on underflow + * + *------------------------------------------------------------------------- + */ +static int +test_conv_flt_1_hw_conv_from_double(void *hw_dst, unsigned char *src_buf, size_t idx, dtype_t dst_type) +{ + double aligned; + int ret = 0; + + memcpy(&aligned, src_buf + idx * sizeof(double), sizeof(double)); + + switch (dst_type) { + case FLT_FLOAT: + *((float *)hw_dst) = (float)aligned; + + /* Check for overflow and underflow */ + if (fabs(aligned) > (double)FLT_MAX) + ret = 1; + else if (fabs(aligned) < (double)FLT_MIN) + ret = 2; + + break; + case FLT_DOUBLE: + *((double *)hw_dst) = aligned; + break; +#if H5_SIZEOF_LONG_DOUBLE != H5_SIZEOF_DOUBLE + case FLT_LDOUBLE: + *((long double *)hw_dst) = (long double)aligned; + break; +#endif + case FLT_FLOAT16: +#ifdef H5_HAVE__FLOAT16 + /* Suppress warning about non-standard floating-point literal suffix */ + H5_GCC_CLANG_DIAG_OFF("pedantic") + + *((H5__Float16 *)hw_dst) = (H5__Float16)aligned; + + /* Check for overflow and underflow */ + if (fabs(aligned) > (double)FLT16_MAX) + ret = 1; + else if (fabs(aligned) < (double)FLT16_MIN) + ret = 2; + + H5_GCC_CLANG_DIAG_ON("pedantic") + break; +#endif + case INT_SCHAR: + case INT_UCHAR: + case INT_SHORT: + case INT_USHORT: + case INT_INT: + case INT_UINT: + case INT_LONG: + case INT_ULONG: + case INT_LLONG: + case INT_ULLONG: + case OTHER: + default: + H5_FAILED(); + printf("invalid destination conversion datatype"); + ret = -1; + goto done; + } + +done: + return ret; +} + +/*------------------------------------------------------------------------- + * Function: test_conv_flt_1_hw_conv_from_ldouble + * + * Purpose: Helper function for test_conv_flt_1 to perform conversion + * from long double to another type by casting. Also checks + * for overflow and underflow when the destination type is a + * type with a smaller width than long double. + * + * Return: -1 on failure + * 0 on success without overflow or underflow + * 1 on overflow + * 2 on underflow + * + *------------------------------------------------------------------------- + */ +#if H5_SIZEOF_LONG_DOUBLE != H5_SIZEOF_DOUBLE +static int +test_conv_flt_1_hw_conv_from_ldouble(void *hw_dst, unsigned char *src_buf, size_t idx, dtype_t dst_type) +{ + long double aligned; + int ret = 0; + + memcpy(&aligned, src_buf + idx * sizeof(long double), sizeof(long double)); + + switch (dst_type) { + case FLT_FLOAT: + *((float *)hw_dst) = (float)aligned; + + /* Check for overflow and underflow */ + if (fabsl(aligned) > (long double)FLT_MAX) + ret = 1; + else if (fabsl(aligned) < (long double)FLT_MIN) + ret = 2; + + break; + case FLT_DOUBLE: + *((double *)hw_dst) = (double)aligned; + + /* Check for overflow and underflow */ + if (fabsl(aligned) > (long double)DBL_MAX) + ret = 1; + else if (fabsl(aligned) < (long double)DBL_MIN) + ret = 2; + + break; + case FLT_LDOUBLE: + *((long double *)hw_dst) = aligned; + break; + case FLT_FLOAT16: +#ifdef H5_HAVE__FLOAT16 + /* Suppress warning about non-standard floating-point literal suffix */ + H5_GCC_CLANG_DIAG_OFF("pedantic") + + *((H5__Float16 *)hw_dst) = (H5__Float16)aligned; + + /* Check for overflow and underflow */ + if (fabsl(aligned) > (long double)FLT16_MAX) + ret = 1; + else if (fabsl(aligned) < (long double)FLT16_MIN) + ret = 2; + + H5_GCC_CLANG_DIAG_ON("pedantic") + break; +#endif + case INT_SCHAR: + case INT_UCHAR: + case INT_SHORT: + case INT_USHORT: + case INT_INT: + case INT_UINT: + case INT_LONG: + case INT_ULONG: + case INT_LLONG: + case INT_ULLONG: + case OTHER: + default: + H5_FAILED(); + printf("invalid destination conversion datatype"); + ret = -1; + goto done; + } + +done: + return ret; +} +#endif + +/*------------------------------------------------------------------------- * Function: test_conv_flt_1 * * Purpose: Test conversion of floating point values from SRC to - * DST. These types should be H5T_NATIVE_FLOAT, - * H5T_NATIVE_DOUBLE, or H5T_NATIVE_LDOUBLE. + * DST. These types should be H5T_NATIVE_FLOAT, + * H5T_NATIVE_DOUBLE, H5T_NATIVE_LDOUBLE or H5T_NATIVE_FLOAT16, + * if available. * * Return: Success: 0 - * - * Failure: number of errors + * Failure: number of errors * *------------------------------------------------------------------------- */ @@ -2762,8 +3195,12 @@ test_conv_flt_1(const char *name, int run_test, hid_t src, hid_t dst) unsigned char *saved = NULL; /*original values */ char str[256]; /*hello string */ void *aligned = NULL; /*aligned buffer */ - float hw_f; /*hardware-converted */ - double hw_d; /*hardware-converted */ + void *hw_p = NULL; + float hw_f; /*hardware-converted */ + double hw_d; /*hardware-converted */ +#ifdef H5_HAVE__FLOAT16 + H5__Float16 hw_half; +#endif #if H5_SIZEOF_LONG_DOUBLE != H5_SIZEOF_DOUBLE long double hw_ld; /*hardware-converted */ #endif @@ -2841,6 +3278,12 @@ test_conv_flt_1(const char *name, int run_test, hid_t src, hid_t dst) src_type = FLT_LDOUBLE; #endif } +#ifdef H5_HAVE__FLOAT16 + else if (H5Tequal(src, H5T_NATIVE_FLOAT16)) { + src_type_name = "_Float16"; + src_type = FLT_FLOAT16; + } +#endif else { src_type_name = "UNKNOWN"; src_type = OTHER; @@ -2860,6 +3303,12 @@ test_conv_flt_1(const char *name, int run_test, hid_t src, hid_t dst) dst_type = FLT_LDOUBLE; #endif } +#ifdef H5_HAVE__FLOAT16 + else if (H5Tequal(dst, H5T_NATIVE_FLOAT16)) { + dst_type_name = "_Float16"; + dst_type = FLT_FLOAT16; + } +#endif else { dst_type_name = "UNKNOWN"; dst_type = OTHER; @@ -2941,6 +3390,23 @@ test_conv_flt_1(const char *name, int run_test, hid_t src, hid_t dst) dst_size, buf, saved, nelmts); #endif } + else if (src_type == FLT_FLOAT16) { +#ifdef H5_HAVE__FLOAT16 + /* Suppress warning about non-standard floating-point literal suffix */ + H5_GCC_CLANG_DIAG_OFF("pedantic") + /* Suppress warning about float conversion in macro code path + * that sets H5__Float16 multiply = 100000000;, which shouldn't + * happen due to the small value of FLT16_MAX_10_EXP. + */ + H5_GCC_CLANG_DIAG_OFF("float-conversion") + INIT_FP_NORM(H5__Float16, FLT16_MAX, FLT16_MIN, FLT16_MAX_10_EXP, FLT16_MIN_10_EXP, src_size, + dst_size, buf, saved, nelmts); + H5_GCC_CLANG_DIAG_ON("float-conversion") + H5_GCC_CLANG_DIAG_ON("pedantic") +#else + assert(0 && "Should not reach this point!"); +#endif + } else goto error; @@ -2960,6 +3426,14 @@ test_conv_flt_1(const char *name, int run_test, hid_t src, hid_t dst) nelmts); #endif } + else if (src_type == FLT_FLOAT16) { +#ifdef H5_HAVE__FLOAT16 + INIT_FP_DENORM(H5__Float16, FLT16_MANT_DIG, src_size, src_nbits, sendian, dst_size, buf, + saved, nelmts); +#else + assert(0 && "Should not reach this point!"); +#endif + } else goto error; @@ -2977,6 +3451,13 @@ test_conv_flt_1(const char *name, int run_test, hid_t src, hid_t dst) INIT_FP_SPECIAL(src_size, src_nbits, sendian, LDBL_MANT_DIG, dst_size, buf, saved, nelmts); #endif } + else if (src_type == FLT_FLOAT16) { +#ifdef H5_HAVE__FLOAT16 + INIT_FP_SPECIAL(src_size, src_nbits, sendian, FLT16_MANT_DIG, dst_size, buf, saved, nelmts); +#else + assert(0 && "Should not reach this point!"); +#endif + } else goto error; @@ -2989,74 +3470,62 @@ test_conv_flt_1(const char *name, int run_test, hid_t src, hid_t dst) if (H5Tconvert(src, dst, nelmts, buf, NULL, H5P_DEFAULT) < 0) goto error; + /* Set pointer to matching type for hardware conversion */ + if (FLT_FLOAT == dst_type) + hw_p = &hw_f; + else if (FLT_DOUBLE == dst_type) + hw_p = &hw_d; +#if H5_SIZEOF_LONG_DOUBLE != H5_SIZEOF_DOUBLE + else if (FLT_LDOUBLE == dst_type) + hw_p = &hw_ld; +#endif +#ifdef H5_HAVE__FLOAT16 + else if (FLT_FLOAT16 == dst_type) + hw_p = &hw_half; +#endif + else + goto error; + + /* Set convenience pointer for indexing into bytes of matching type */ + hw = (unsigned char *)hw_p; + /* Check the software results against the hardware */ for (j = 0; j < nelmts; j++) { - underflow = 0; - hw_f = 911.0F; - hw_d = 911.0; + int conv_ret = -1; + + hw_f = 911.0F; + hw_d = 911.0; #if H5_SIZEOF_LONG_DOUBLE != H5_SIZEOF_DOUBLE hw_ld = 911.0L; #endif +#ifdef H5_HAVE__FLOAT16 + hw_half = 911.0; +#endif /* The hardware conversion */ - /* Check for underflow when src is a "larger" float than dst.*/ - if (FLT_FLOAT == src_type) { - memcpy(aligned, saved + j * sizeof(float), sizeof(float)); - if (FLT_FLOAT == dst_type) { - hw_f = *((float *)aligned); - hw = (unsigned char *)&hw_f; - } - else if (FLT_DOUBLE == dst_type) { - hw_d = (double)*((float *)aligned); - hw = (unsigned char *)&hw_d; -#if H5_SIZEOF_LONG_DOUBLE != H5_SIZEOF_DOUBLE - } - else { - hw_ld = (long double)*((float *)aligned); - hw = (unsigned char *)&hw_ld; +#ifdef H5_HAVE__FLOAT16 + if (FLT_FLOAT16 == src_type) { + conv_ret = test_conv_flt_1_hw_conv_from_flt16(hw_p, saved, j, dst_type); + } + else #endif - } + if (FLT_FLOAT == src_type) { + conv_ret = test_conv_flt_1_hw_conv_from_flt(hw_p, saved, j, dst_type); } else if (FLT_DOUBLE == src_type) { - memcpy(aligned, saved + j * sizeof(double), sizeof(double)); - if (FLT_FLOAT == dst_type) { - hw_f = (float)(*((double *)aligned)); - hw = (unsigned char *)&hw_f; - underflow = fabs(*((double *)aligned)) < (double)FLT_MIN; - overflow = fabs(*((double *)aligned)) > (double)FLT_MAX; - } - else if (FLT_DOUBLE == dst_type) { - hw_d = *((double *)aligned); - hw = (unsigned char *)&hw_d; -#if H5_SIZEOF_LONG_DOUBLE != H5_SIZEOF_DOUBLE - } - else { - hw_ld = (long double)*((double *)aligned); - hw = (unsigned char *)&hw_ld; -#endif - } + conv_ret = test_conv_flt_1_hw_conv_from_double(hw_p, saved, j, dst_type); + } #if H5_SIZEOF_LONG_DOUBLE != H5_SIZEOF_DOUBLE + else if (FLT_LDOUBLE == src_type) { + conv_ret = test_conv_flt_1_hw_conv_from_ldouble(hw_p, saved, j, dst_type); } - else { - memcpy(aligned, saved + j * sizeof(long double), sizeof(long double)); - if (FLT_FLOAT == dst_type) { - hw_f = (float)*((long double *)aligned); - hw = (unsigned char *)&hw_f; - underflow = fabsl(*((long double *)aligned)) < (long double)FLT_MIN; - overflow = fabsl(*((long double *)aligned)) > (long double)FLT_MAX; - } - else if (FLT_DOUBLE == dst_type) { - hw_d = (double)*((long double *)aligned); - hw = (unsigned char *)&hw_d; - underflow = fabsl(*((long double *)aligned)) < (long double)DBL_MIN; - overflow = fabsl(*((long double *)aligned)) > (long double)DBL_MAX; - } - else { - hw_ld = *((long double *)aligned); - hw = (unsigned char *)&hw_ld; - } #endif - } + + if (conv_ret < 0) + goto error; + + overflow = (conv_ret == 1); + underflow = (conv_ret == 2); /* For Intel machines, the size of "long double" is 12 bytes, precision * is 80 bits; for Intel IA64 and AMD processors, the size of "long double" @@ -3099,6 +3568,12 @@ test_conv_flt_1(const char *name, int run_test, hid_t src, hid_t dst) continue; #endif } +#ifdef H5_HAVE__FLOAT16 + else if (FLT_FLOAT16 == dst_type && my_isnan(dst_type, buf + j * sizeof(H5__Float16)) && + my_isnan(dst_type, hw)) { + continue; + } +#endif /* * Assume same if hardware result is NaN. This is because the @@ -3148,7 +3623,7 @@ test_conv_flt_1(const char *name, int run_test, hid_t src, hid_t dst) check_mant[1] = frexp(hw_d, check_expo + 1); #if (H5_SIZEOF_LONG_DOUBLE != H5_SIZEOF_DOUBLE) } - else { + else if (FLT_LDOUBLE == dst_type) { long double x = 0.0L; memcpy(&x, &buf[j * dst_size], sizeof(long double)); /* dst is largest float, no need to check underflow. */ @@ -3156,6 +3631,35 @@ test_conv_flt_1(const char *name, int run_test, hid_t src, hid_t dst) check_mant[1] = (double)frexpl(hw_ld, check_expo + 1); #endif } + else if (FLT_FLOAT16 == dst_type) { +#ifdef H5_HAVE__FLOAT16 + H5__Float16 x; + memcpy(&x, &buf[j * dst_size], sizeof(H5__Float16)); + + /* Suppress warning about non-standard floating-point literal suffix */ + H5_GCC_CLANG_DIAG_OFF("pedantic") +#ifdef H5_HAVE_FABSF16 + if (underflow && fabsf16(x) <= FLT16_MIN && fabsf16(hw_half) <= FLT16_MIN) + continue; /* all underflowed, no error */ +#else + if (underflow && fabsf((float)x) <= (float)FLT16_MIN && + fabsf((float)hw_half) <= (float)FLT16_MIN) + continue; /* all underflowed, no error */ +#endif + H5_GCC_CLANG_DIAG_ON("pedantic") + + if (overflow && my_isinf(dendian, buf + j * sizeof(H5__Float16), dst_size, dst_mpos, + dst_msize, dst_epos, dst_esize)) + continue; /* all overflowed, no error */ + check_mant[0] = (double)frexpf((float)x, check_expo + 0); + check_mant[1] = (double)frexpf((float)hw_half, check_expo + 1); +#else + assert(0 && "Should not reach this point!"); +#endif + } + else + goto error; + /* Special check for denormalized values */ if (check_expo[0] < (-(int)dst_ebias) || check_expo[1] < (-(int)dst_ebias)) { int expo_diff = check_expo[0] - check_expo[1]; @@ -3206,12 +3710,23 @@ test_conv_flt_1(const char *name, int run_test, hid_t src, hid_t dst) printf(" %29.20e\n", x); #if H5_SIZEOF_LONG_DOUBLE != H5_SIZEOF_DOUBLE } - else { + else if (FLT_LDOUBLE == src_type) { long double x = 0.0L; memcpy(&x, &saved[j * src_size], sizeof(long double)); fprintf(stdout, " %29.20Le\n", x); #endif } + else if (FLT_FLOAT16 == src_type) { +#ifdef H5_HAVE__FLOAT16 + H5__Float16 x; + memcpy(&x, &saved[j * src_size], sizeof(H5__Float16)); + printf(" %29.20e\n", (double)x); +#else + assert(0 && "Should not reach this point!"); +#endif + } + else + goto error; printf(" dst ="); for (k = 0; k < dst_size; k++) @@ -3228,12 +3743,23 @@ test_conv_flt_1(const char *name, int run_test, hid_t src, hid_t dst) printf(" %29.20e\n", x); #if H5_SIZEOF_LONG_DOUBLE != H5_SIZEOF_DOUBLE } - else { + else if (FLT_LDOUBLE == src_type) { long double x = 0.0L; memcpy(&x, &buf[j * dst_size], sizeof(long double)); fprintf(stdout, " %29.20Le\n", x); #endif } + else if (FLT_FLOAT16 == src_type) { +#ifdef H5_HAVE__FLOAT16 + H5__Float16 x; + memcpy(&x, &buf[j * dst_size], sizeof(H5__Float16)); + printf(" %29.20e\n", (double)x); +#else + assert(0 && "Should not reach this point!"); +#endif + } + else + goto error; printf(" ans ="); for (k = 0; k < dst_size; k++) @@ -3244,9 +3770,15 @@ test_conv_flt_1(const char *name, int run_test, hid_t src, hid_t dst) else if (FLT_DOUBLE == dst_type) printf(" %29.20e\n", hw_d); #if H5_SIZEOF_LONG_DOUBLE != H5_SIZEOF_DOUBLE - else + else if (FLT_LDOUBLE == dst_type) fprintf(stdout, " %29.20Le\n", hw_ld); #endif +#ifdef H5_HAVE__FLOAT16 + else if (FLT_FLOAT16 == dst_type) + printf(" %29.20e\n", (double)hw_half); +#endif + else + goto error; /* If the source is normalized values, print out error message; if it is * denormalized or special values, print out warning message.*/ @@ -3326,17 +3858,16 @@ error: * Function: test_conv_int_fp * * Purpose: Test conversion between integer and float values - * from SRC to DST. These types should be any combination of: + * from SRC to DST. These types should be any combination of: * * H5T_NATIVE_SCHAR H5T_NATIVE_FLOAT - * H5T_NATIVE_SHORT H5T_NATIVE_DOUBLE - * H5T_NATIVE_INT H5T_NATIVE_LDOUBLE - * H5T_NATIVE_LONG - * H5T_NATIVE_LLONG + * H5T_NATIVE_SHORT H5T_NATIVE_DOUBLE + * H5T_NATIVE_INT H5T_NATIVE_LDOUBLE + * H5T_NATIVE_LONG + * H5T_NATIVE_LLONG * * Return: Success: 0 - * - * Failure: number of errors + * Failure: number of errors * *------------------------------------------------------------------------- */ @@ -3382,6 +3913,9 @@ test_conv_int_fp(const char *name, int run_test, hid_t src, hid_t dst) unsigned long hw_ulong = 0; long long hw_llong = 0; unsigned long long hw_ullong = 0; +#ifdef H5_HAVE__FLOAT16 + H5__Float16 hw_half; +#endif /* What is the name of the source type */ if (H5Tequal(src, H5T_NATIVE_SCHAR)) { @@ -3438,6 +3972,12 @@ test_conv_int_fp(const char *name, int run_test, hid_t src, hid_t dst) src_type = FLT_LDOUBLE; #endif } +#ifdef H5_HAVE__FLOAT16 + else if (H5Tequal(src, H5T_NATIVE_FLOAT16)) { + src_type_name = "_Float16"; + src_type = FLT_FLOAT16; + } +#endif else { src_type_name = "UNKNOWN"; src_type = OTHER; @@ -3498,6 +4038,12 @@ test_conv_int_fp(const char *name, int run_test, hid_t src, hid_t dst) dst_type = FLT_LDOUBLE; #endif } +#ifdef H5_HAVE__FLOAT16 + else if (H5Tequal(dst, H5T_NATIVE_FLOAT16)) { + dst_type_name = "_Float16"; + dst_type = FLT_FLOAT16; + } +#endif else { dst_type_name = "UNKNOWN"; dst_type = OTHER; @@ -3515,7 +4061,8 @@ test_conv_int_fp(const char *name, int run_test, hid_t src, hid_t dst) if ((INT_SCHAR == src_type || INT_UCHAR == src_type || INT_SHORT == src_type || INT_USHORT == src_type || INT_INT == src_type || INT_UINT == src_type || INT_LONG == src_type || INT_ULONG == src_type || INT_LLONG == src_type || INT_ULLONG == src_type) && - (FLT_FLOAT != dst_type && FLT_DOUBLE != dst_type && FLT_LDOUBLE != dst_type)) { + (FLT_FLOAT != dst_type && FLT_DOUBLE != dst_type && FLT_LDOUBLE != dst_type && + FLT_FLOAT16 != dst_type)) { snprintf(str, sizeof(str), "Testing %s %s -> %s conversions", name, src_type_name, dst_type_name); printf("%-70s", str); H5_FAILED(); @@ -3523,7 +4070,8 @@ test_conv_int_fp(const char *name, int run_test, hid_t src, hid_t dst) goto error; } - if ((FLT_FLOAT == src_type || FLT_DOUBLE == src_type || FLT_LDOUBLE == src_type) && + if ((FLT_FLOAT == src_type || FLT_DOUBLE == src_type || FLT_LDOUBLE == src_type || + FLT_FLOAT16 == src_type) && (INT_SCHAR != dst_type && INT_UCHAR != dst_type && INT_SHORT != dst_type && INT_USHORT != dst_type && INT_INT != dst_type && INT_UINT != dst_type && INT_LONG != dst_type && INT_ULONG != dst_type && INT_LLONG != dst_type && INT_ULLONG != dst_type)) { @@ -3671,6 +4219,32 @@ test_conv_int_fp(const char *name, int run_test, hid_t src, hid_t dst) } #endif } + else if (src_type == FLT_FLOAT16) { +#ifdef H5_HAVE__FLOAT16 + if (run_test == TEST_NORMAL) { + /* Suppress warning about non-standard floating-point literal suffix */ + H5_GCC_CLANG_DIAG_OFF("pedantic") + /* Suppress warning about float conversion in macro code path + * that sets H5__Float16 multiply = 100000000;, which shouldn't + * happen due to the small value of FLT16_MAX_10_EXP. + */ + H5_GCC_CLANG_DIAG_OFF("float-conversion") + INIT_FP_NORM(H5__Float16, FLT16_MAX, FLT16_MIN, FLT16_MAX_10_EXP, FLT16_MIN_10_EXP, src_size, + dst_size, buf, saved, nelmts); + H5_GCC_CLANG_DIAG_ON("float-conversion") + H5_GCC_CLANG_DIAG_ON("pedantic") + } + else if (run_test == TEST_DENORM) { + INIT_FP_DENORM(H5__Float16, FLT16_MANT_DIG, src_size, src_nbits, sendian, dst_size, buf, saved, + nelmts); + } + else { + INIT_FP_SPECIAL(src_size, src_nbits, sendian, FLT16_MANT_DIG, dst_size, buf, saved, nelmts); + } +#else + assert(0 && "Should not reach this point!"); +#endif + } else goto error; @@ -3680,7 +4254,8 @@ test_conv_int_fp(const char *name, int run_test, hid_t src, hid_t dst) /* Check the results from the library against hardware */ for (j = 0; j < nelmts; j++) { - if (FLT_FLOAT == src_type || FLT_DOUBLE == src_type || FLT_LDOUBLE == src_type) + if (FLT_FLOAT == src_type || FLT_DOUBLE == src_type || FLT_LDOUBLE == src_type || + FLT_FLOAT16 == src_type) if (my_isnan(src_type, saved + j * src_size)) continue; @@ -3727,6 +4302,7 @@ test_conv_int_fp(const char *name, int run_test, hid_t src, hid_t dst) memcpy(aligned, saved + j * sizeof(unsigned long long), sizeof(unsigned long long)); hw_float = (float)(*((unsigned long long *)aligned)); break; + case FLT_FLOAT16: case FLT_FLOAT: case FLT_DOUBLE: case FLT_LDOUBLE: @@ -3779,6 +4355,7 @@ test_conv_int_fp(const char *name, int run_test, hid_t src, hid_t dst) memcpy(aligned, saved + j * sizeof(unsigned long long), sizeof(unsigned long long)); hw_double = (double)(*((unsigned long long *)aligned)); break; + case FLT_FLOAT16: case FLT_FLOAT: case FLT_DOUBLE: case FLT_LDOUBLE: @@ -3831,6 +4408,7 @@ test_conv_int_fp(const char *name, int run_test, hid_t src, hid_t dst) memcpy(aligned, saved + j * sizeof(unsigned long long), sizeof(unsigned long long)); hw_ldouble = (long double)(*((unsigned long long *)aligned)); break; + case FLT_FLOAT16: case FLT_FLOAT: case FLT_DOUBLE: case FLT_LDOUBLE: @@ -3840,6 +4418,63 @@ test_conv_int_fp(const char *name, int run_test, hid_t src, hid_t dst) break; } } + else if (FLT_FLOAT16 == dst_type) { +#ifdef H5_HAVE__FLOAT16 + hw = (unsigned char *)&hw_half; + switch (src_type) { + case INT_SCHAR: + memcpy(aligned, saved + j * sizeof(signed char), sizeof(signed char)); + hw_half = (H5__Float16)(*((signed char *)aligned)); + break; + case INT_UCHAR: + memcpy(aligned, saved + j * sizeof(unsigned char), sizeof(unsigned char)); + hw_half = (H5__Float16)(*((unsigned char *)aligned)); + break; + case INT_SHORT: + memcpy(aligned, saved + j * sizeof(short), sizeof(short)); + hw_half = (H5__Float16)(*((short *)aligned)); + break; + case INT_USHORT: + memcpy(aligned, saved + j * sizeof(unsigned short), sizeof(unsigned short)); + hw_half = (H5__Float16)(*((unsigned short *)aligned)); + break; + case INT_INT: + memcpy(aligned, saved + j * sizeof(int), sizeof(int)); + hw_half = (H5__Float16)(*((int *)aligned)); + break; + case INT_UINT: + memcpy(aligned, saved + j * sizeof(unsigned), sizeof(unsigned)); + hw_half = (H5__Float16)(*((unsigned *)aligned)); + break; + case INT_LONG: + memcpy(aligned, saved + j * sizeof(long), sizeof(long)); + hw_half = (H5__Float16)(*((long *)aligned)); + break; + case INT_ULONG: + memcpy(aligned, saved + j * sizeof(unsigned long), sizeof(unsigned long)); + hw_half = (H5__Float16)(*((unsigned long *)aligned)); + break; + case INT_LLONG: + memcpy(aligned, saved + j * sizeof(long long), sizeof(long long)); + hw_half = (H5__Float16)(*((long long *)aligned)); + break; + case INT_ULLONG: + memcpy(aligned, saved + j * sizeof(unsigned long long), sizeof(unsigned long long)); + hw_half = (H5__Float16)(*((unsigned long long *)aligned)); + break; + case FLT_FLOAT16: + case FLT_FLOAT: + case FLT_DOUBLE: + case FLT_LDOUBLE: + case OTHER: + default: + assert(0 && "Unknown type"); + break; + } +#else + assert(0 && "Should not reach this point!"); +#endif + } else if (INT_SCHAR == dst_type) { hw = (unsigned char *)&hw_schar; switch (src_type) { @@ -3855,6 +4490,14 @@ test_conv_int_fp(const char *name, int run_test, hid_t src, hid_t dst) memcpy(aligned, saved + j * sizeof(long double), sizeof(long double)); hw_schar = (signed char)(*((long double *)aligned)); break; + case FLT_FLOAT16: +#ifdef H5_HAVE__FLOAT16 + memcpy(aligned, saved + j * sizeof(H5__Float16), sizeof(H5__Float16)); + hw_schar = (signed char)(*((H5__Float16 *)aligned)); + break; +#else + assert(0 && "Should not reach this point!"); +#endif case INT_SCHAR: case INT_UCHAR: case INT_SHORT: @@ -3886,6 +4529,14 @@ test_conv_int_fp(const char *name, int run_test, hid_t src, hid_t dst) memcpy(aligned, saved + j * sizeof(long double), sizeof(long double)); hw_uchar = (unsigned char)(*((long double *)aligned)); break; + case FLT_FLOAT16: +#ifdef H5_HAVE__FLOAT16 + memcpy(aligned, saved + j * sizeof(H5__Float16), sizeof(H5__Float16)); + hw_uchar = (unsigned char)(*((H5__Float16 *)aligned)); + break; +#else + assert(0 && "Should not reach this point!"); +#endif case INT_SCHAR: case INT_UCHAR: case INT_SHORT: @@ -3917,6 +4568,14 @@ test_conv_int_fp(const char *name, int run_test, hid_t src, hid_t dst) memcpy(aligned, saved + j * sizeof(long double), sizeof(long double)); hw_short = (short)(*((long double *)aligned)); break; + case FLT_FLOAT16: +#ifdef H5_HAVE__FLOAT16 + memcpy(aligned, saved + j * sizeof(H5__Float16), sizeof(H5__Float16)); + hw_short = (short)(*((H5__Float16 *)aligned)); + break; +#else + assert(0 && "Should not reach this point!"); +#endif case INT_SCHAR: case INT_UCHAR: case INT_SHORT: @@ -3948,6 +4607,14 @@ test_conv_int_fp(const char *name, int run_test, hid_t src, hid_t dst) memcpy(aligned, saved + j * sizeof(long double), sizeof(long double)); hw_ushort = (unsigned short)(*((long double *)aligned)); break; + case FLT_FLOAT16: +#ifdef H5_HAVE__FLOAT16 + memcpy(aligned, saved + j * sizeof(H5__Float16), sizeof(H5__Float16)); + hw_ushort = (unsigned short)(*((H5__Float16 *)aligned)); + break; +#else + assert(0 && "Should not reach this point!"); +#endif case INT_SCHAR: case INT_UCHAR: case INT_SHORT: @@ -3979,6 +4646,14 @@ test_conv_int_fp(const char *name, int run_test, hid_t src, hid_t dst) memcpy(aligned, saved + j * sizeof(long double), sizeof(long double)); hw_int = (int)(*((long double *)aligned)); break; + case FLT_FLOAT16: +#ifdef H5_HAVE__FLOAT16 + memcpy(aligned, saved + j * sizeof(H5__Float16), sizeof(H5__Float16)); + hw_int = (int)(*((H5__Float16 *)aligned)); + break; +#else + assert(0 && "Should not reach this point!"); +#endif case INT_SCHAR: case INT_UCHAR: case INT_SHORT: @@ -4010,6 +4685,14 @@ test_conv_int_fp(const char *name, int run_test, hid_t src, hid_t dst) memcpy(aligned, saved + j * sizeof(long double), sizeof(long double)); hw_uint = (unsigned int)(*((long double *)aligned)); break; + case FLT_FLOAT16: +#ifdef H5_HAVE__FLOAT16 + memcpy(aligned, saved + j * sizeof(H5__Float16), sizeof(H5__Float16)); + hw_uint = (unsigned int)(*((H5__Float16 *)aligned)); + break; +#else + assert(0 && "Should not reach this point!"); +#endif case INT_SCHAR: case INT_UCHAR: case INT_SHORT: @@ -4041,6 +4724,14 @@ test_conv_int_fp(const char *name, int run_test, hid_t src, hid_t dst) memcpy(aligned, saved + j * sizeof(long double), sizeof(long double)); hw_long = (long)(*((long double *)aligned)); break; + case FLT_FLOAT16: +#ifdef H5_HAVE__FLOAT16 + memcpy(aligned, saved + j * sizeof(H5__Float16), sizeof(H5__Float16)); + hw_long = (long)(*((H5__Float16 *)aligned)); + break; +#else + assert(0 && "Should not reach this point!"); +#endif case INT_SCHAR: case INT_UCHAR: case INT_SHORT: @@ -4072,6 +4763,14 @@ test_conv_int_fp(const char *name, int run_test, hid_t src, hid_t dst) memcpy(aligned, saved + j * sizeof(long double), sizeof(long double)); hw_ulong = (unsigned long)(*((long double *)aligned)); break; + case FLT_FLOAT16: +#ifdef H5_HAVE__FLOAT16 + memcpy(aligned, saved + j * sizeof(H5__Float16), sizeof(H5__Float16)); + hw_ulong = (unsigned long)(*((H5__Float16 *)aligned)); + break; +#else + assert(0 && "Should not reach this point!"); +#endif case INT_SCHAR: case INT_UCHAR: case INT_SHORT: @@ -4103,6 +4802,14 @@ test_conv_int_fp(const char *name, int run_test, hid_t src, hid_t dst) memcpy(aligned, saved + j * sizeof(long double), sizeof(long double)); hw_llong = (long long)(*((long double *)aligned)); break; + case FLT_FLOAT16: +#ifdef H5_HAVE__FLOAT16 + memcpy(aligned, saved + j * sizeof(H5__Float16), sizeof(H5__Float16)); + hw_llong = (long long)(*((H5__Float16 *)aligned)); + break; +#else + assert(0 && "Should not reach this point!"); +#endif case INT_SCHAR: case INT_UCHAR: case INT_SHORT: @@ -4134,6 +4841,14 @@ test_conv_int_fp(const char *name, int run_test, hid_t src, hid_t dst) memcpy(aligned, saved + j * sizeof(long double), sizeof(long double)); hw_ullong = (unsigned long long)(*((long double *)aligned)); break; + case FLT_FLOAT16: +#ifdef H5_HAVE__FLOAT16 + memcpy(aligned, saved + j * sizeof(H5__Float16), sizeof(H5__Float16)); + hw_ullong = (unsigned long long)(*((H5__Float16 *)aligned)); + break; +#else + assert(0 && "Should not reach this point!"); +#endif case INT_SCHAR: case INT_UCHAR: case INT_SHORT: @@ -4204,7 +4919,8 @@ test_conv_int_fp(const char *name, int run_test, hid_t src, hid_t dst) * Try to follow the except_func callback function to check if the * desired value was set. */ - if ((FLT_FLOAT == src_type || FLT_DOUBLE == src_type || FLT_LDOUBLE == src_type) && + if ((FLT_FLOAT == src_type || FLT_DOUBLE == src_type || FLT_LDOUBLE == src_type || + FLT_FLOAT16 == src_type) && (INT_SCHAR == dst_type || INT_SHORT == dst_type || INT_INT == dst_type || INT_LONG == dst_type || INT_LLONG == dst_type)) { if (0 == H5T__bit_get_d(src_bits, src_nbits - 1, (size_t)1) && @@ -4244,7 +4960,8 @@ test_conv_int_fp(const char *name, int run_test, hid_t src, hid_t dst) } } - if ((FLT_FLOAT == src_type || FLT_DOUBLE == src_type || FLT_LDOUBLE == src_type) && + if ((FLT_FLOAT == src_type || FLT_DOUBLE == src_type || FLT_LDOUBLE == src_type || + FLT_FLOAT16 == src_type) && (INT_UCHAR == dst_type || INT_USHORT == dst_type || INT_UINT == dst_type || INT_ULONG == dst_type || INT_ULLONG == dst_type)) { if (H5T__bit_get_d(src_bits, src_nbits - 1, (size_t)1)) { @@ -4347,6 +5064,14 @@ test_conv_int_fp(const char *name, int run_test, hid_t src, hid_t dst) memcpy(aligned, saved + j * sizeof(long double), sizeof(long double)); printf(" %29Lf\n", *((long double *)aligned)); break; + case FLT_FLOAT16: +#ifdef H5_HAVE__FLOAT16 + memcpy(aligned, saved + j * sizeof(H5__Float16), sizeof(H5__Float16)); + printf(" %29f\n", (double)*((H5__Float16 *)aligned)); + break; +#else + assert(0 && "Should not reach this point!"); +#endif case OTHER: default: assert(0 && "Unknown type"); @@ -4410,6 +5135,14 @@ test_conv_int_fp(const char *name, int run_test, hid_t src, hid_t dst) memcpy(aligned, buf + j * sizeof(long double), sizeof(long double)); printf(" %29Lf\n", *((long double *)aligned)); break; + case FLT_FLOAT16: +#ifdef H5_HAVE__FLOAT16 + memcpy(aligned, buf + j * sizeof(H5__Float16), sizeof(H5__Float16)); + printf(" %29f\n", (double)*((H5__Float16 *)aligned)); + break; +#else + assert(0 && "Should not reach this point!"); +#endif case OTHER: default: assert(0 && "Unknown type"); @@ -4460,6 +5193,13 @@ test_conv_int_fp(const char *name, int run_test, hid_t src, hid_t dst) case FLT_LDOUBLE: printf(" %29Lf\n", *((long double *)((void *)hw))); break; + case FLT_FLOAT16: +#ifdef H5_HAVE__FLOAT16 + printf(" %29f\n", (double)*((H5__Float16 *)((void *)hw))); + break; +#else + assert(0 && "Should not reach this point!"); +#endif case OTHER: default: assert(0 && "Unknown type"); @@ -4784,6 +5524,9 @@ run_fp_tests(const char *name) nerrors += test_conv_flt_1("noop", TEST_NOOP, H5T_NATIVE_FLOAT, H5T_NATIVE_FLOAT); nerrors += test_conv_flt_1("noop", TEST_NOOP, H5T_NATIVE_DOUBLE, H5T_NATIVE_DOUBLE); nerrors += test_conv_flt_1("noop", TEST_NOOP, H5T_NATIVE_LDOUBLE, H5T_NATIVE_LDOUBLE); +#ifdef H5_HAVE__FLOAT16 + nerrors += test_conv_flt_1("noop", TEST_NOOP, H5T_NATIVE_FLOAT16, H5T_NATIVE_FLOAT16); +#endif goto done; } @@ -4796,6 +5539,28 @@ run_fp_tests(const char *name) nerrors += test_conv_flt_1(name, TEST_NORMAL, H5T_NATIVE_LDOUBLE, H5T_NATIVE_FLOAT); nerrors += test_conv_flt_1(name, TEST_NORMAL, H5T_NATIVE_LDOUBLE, H5T_NATIVE_DOUBLE); #endif +#ifdef H5_HAVE__FLOAT16 + nerrors += test_conv_flt_1(name, TEST_NORMAL, H5T_NATIVE_FLOAT16, H5T_NATIVE_FLOAT); + nerrors += test_conv_flt_1(name, TEST_NORMAL, H5T_NATIVE_FLOAT16, H5T_NATIVE_DOUBLE); + nerrors += test_conv_flt_1(name, TEST_NORMAL, H5T_NATIVE_FLOAT, H5T_NATIVE_FLOAT16); + nerrors += test_conv_flt_1(name, TEST_NORMAL, H5T_NATIVE_DOUBLE, H5T_NATIVE_FLOAT16); +#if H5_SIZEOF_LONG_DOUBLE != H5_SIZEOF_DOUBLE + nerrors += test_conv_flt_1(name, TEST_NORMAL, H5T_NATIVE_FLOAT16, H5T_NATIVE_LDOUBLE); +#ifdef H5_LDOUBLE_TO_FLOAT16_CORRECT + nerrors += test_conv_flt_1(name, TEST_NORMAL, H5T_NATIVE_LDOUBLE, H5T_NATIVE_FLOAT16); +#else + { + char str[256]; + + snprintf(str, sizeof(str), "Testing %s normalized %s -> %s conversions", name, "long double", + "_Float16"); + printf("%-70s", str); + SKIPPED(); + puts(" Test skipped due to compiler error in handling conversion."); + } +#endif +#endif +#endif /*Test denormalized values. TEST_DENORM indicates denormalized values.*/ nerrors += test_conv_flt_1(name, TEST_DENORM, H5T_NATIVE_FLOAT, H5T_NATIVE_DOUBLE); @@ -4819,6 +5584,28 @@ run_fp_tests(const char *name) nerrors += test_conv_flt_1(name, TEST_DENORM, H5T_NATIVE_LDOUBLE, H5T_NATIVE_DOUBLE); #endif +#ifdef H5_HAVE__FLOAT16 + nerrors += test_conv_flt_1(name, TEST_DENORM, H5T_NATIVE_FLOAT16, H5T_NATIVE_FLOAT); + nerrors += test_conv_flt_1(name, TEST_DENORM, H5T_NATIVE_FLOAT16, H5T_NATIVE_DOUBLE); + nerrors += test_conv_flt_1(name, TEST_DENORM, H5T_NATIVE_FLOAT, H5T_NATIVE_FLOAT16); + nerrors += test_conv_flt_1(name, TEST_DENORM, H5T_NATIVE_DOUBLE, H5T_NATIVE_FLOAT16); +#if H5_SIZEOF_LONG_DOUBLE != H5_SIZEOF_DOUBLE + nerrors += test_conv_flt_1(name, TEST_DENORM, H5T_NATIVE_FLOAT16, H5T_NATIVE_LDOUBLE); +#ifdef H5_LDOUBLE_TO_FLOAT16_CORRECT + nerrors += test_conv_flt_1(name, TEST_DENORM, H5T_NATIVE_LDOUBLE, H5T_NATIVE_FLOAT16); +#else + { + char str[256]; + + snprintf(str, sizeof(str), "Testing %s denormalized %s -> %s conversions", name, "long double", + "_Float16"); + printf("%-70s", str); + SKIPPED(); + puts(" Test skipped due to compiler error in handling conversion."); + } +#endif +#endif +#endif /*Test special values, +/-0, +/-infinity, +/-QNaN, +/-SNaN.*/ nerrors += test_conv_flt_1(name, TEST_SPECIAL, H5T_NATIVE_FLOAT, H5T_NATIVE_DOUBLE); @@ -4841,6 +5628,28 @@ run_fp_tests(const char *name) } #endif #endif +#ifdef H5_HAVE__FLOAT16 + nerrors += test_conv_flt_1(name, TEST_SPECIAL, H5T_NATIVE_FLOAT16, H5T_NATIVE_FLOAT); + nerrors += test_conv_flt_1(name, TEST_SPECIAL, H5T_NATIVE_FLOAT16, H5T_NATIVE_DOUBLE); + nerrors += test_conv_flt_1(name, TEST_SPECIAL, H5T_NATIVE_FLOAT, H5T_NATIVE_FLOAT16); + nerrors += test_conv_flt_1(name, TEST_SPECIAL, H5T_NATIVE_DOUBLE, H5T_NATIVE_FLOAT16); +#if H5_SIZEOF_LONG_DOUBLE != H5_SIZEOF_DOUBLE + nerrors += test_conv_flt_1(name, TEST_SPECIAL, H5T_NATIVE_FLOAT16, H5T_NATIVE_LDOUBLE); +#ifdef H5_LDOUBLE_TO_FLOAT16_CORRECT + nerrors += test_conv_flt_1(name, TEST_SPECIAL, H5T_NATIVE_LDOUBLE, H5T_NATIVE_FLOAT16); +#else + { + char str[256]; + + snprintf(str, sizeof(str), "Testing %s special %s -> %s conversions", name, "long double", + "_Float16"); + printf("%-70s", str); + SKIPPED(); + puts(" Test skipped due to compiler error in handling conversion."); + } +#endif +#endif +#endif done: return nerrors; @@ -4862,36 +5671,66 @@ run_int_fp_conv(const char *name) nerrors += test_conv_int_fp(name, TEST_NORMAL, H5T_NATIVE_SCHAR, H5T_NATIVE_FLOAT); nerrors += test_conv_int_fp(name, TEST_NORMAL, H5T_NATIVE_SCHAR, H5T_NATIVE_DOUBLE); +#ifdef H5_HAVE__FLOAT16 + nerrors += test_conv_int_fp(name, TEST_NORMAL, H5T_NATIVE_SCHAR, H5T_NATIVE_FLOAT16); +#endif nerrors += test_conv_int_fp(name, TEST_NORMAL, H5T_NATIVE_UCHAR, H5T_NATIVE_FLOAT); nerrors += test_conv_int_fp(name, TEST_NORMAL, H5T_NATIVE_UCHAR, H5T_NATIVE_DOUBLE); +#ifdef H5_HAVE__FLOAT16 + nerrors += test_conv_int_fp(name, TEST_NORMAL, H5T_NATIVE_UCHAR, H5T_NATIVE_FLOAT16); +#endif nerrors += test_conv_int_fp(name, TEST_NORMAL, H5T_NATIVE_SHORT, H5T_NATIVE_FLOAT); nerrors += test_conv_int_fp(name, TEST_NORMAL, H5T_NATIVE_SHORT, H5T_NATIVE_DOUBLE); +#ifdef H5_HAVE__FLOAT16 + nerrors += test_conv_int_fp(name, TEST_NORMAL, H5T_NATIVE_SHORT, H5T_NATIVE_FLOAT16); +#endif nerrors += test_conv_int_fp(name, TEST_NORMAL, H5T_NATIVE_USHORT, H5T_NATIVE_FLOAT); nerrors += test_conv_int_fp(name, TEST_NORMAL, H5T_NATIVE_USHORT, H5T_NATIVE_DOUBLE); +#ifdef H5_HAVE__FLOAT16 + nerrors += test_conv_int_fp(name, TEST_NORMAL, H5T_NATIVE_USHORT, H5T_NATIVE_FLOAT16); +#endif nerrors += test_conv_int_fp(name, TEST_NORMAL, H5T_NATIVE_INT, H5T_NATIVE_FLOAT); nerrors += test_conv_int_fp(name, TEST_NORMAL, H5T_NATIVE_INT, H5T_NATIVE_DOUBLE); +#ifdef H5_HAVE__FLOAT16 + nerrors += test_conv_int_fp(name, TEST_NORMAL, H5T_NATIVE_INT, H5T_NATIVE_FLOAT16); +#endif nerrors += test_conv_int_fp(name, TEST_NORMAL, H5T_NATIVE_UINT, H5T_NATIVE_FLOAT); nerrors += test_conv_int_fp(name, TEST_NORMAL, H5T_NATIVE_UINT, H5T_NATIVE_DOUBLE); +#ifdef H5_HAVE__FLOAT16 + nerrors += test_conv_int_fp(name, TEST_NORMAL, H5T_NATIVE_UINT, H5T_NATIVE_FLOAT16); +#endif #if H5_SIZEOF_LONG != H5_SIZEOF_INT nerrors += test_conv_int_fp(name, TEST_NORMAL, H5T_NATIVE_LONG, H5T_NATIVE_FLOAT); nerrors += test_conv_int_fp(name, TEST_NORMAL, H5T_NATIVE_LONG, H5T_NATIVE_DOUBLE); +#ifdef H5_HAVE__FLOAT16 + nerrors += test_conv_int_fp(name, TEST_NORMAL, H5T_NATIVE_LONG, H5T_NATIVE_FLOAT16); +#endif nerrors += test_conv_int_fp(name, TEST_NORMAL, H5T_NATIVE_ULONG, H5T_NATIVE_FLOAT); nerrors += test_conv_int_fp(name, TEST_NORMAL, H5T_NATIVE_ULONG, H5T_NATIVE_DOUBLE); +#ifdef H5_HAVE__FLOAT16 + nerrors += test_conv_int_fp(name, TEST_NORMAL, H5T_NATIVE_ULONG, H5T_NATIVE_FLOAT16); +#endif #endif #if H5_SIZEOF_LONG_LONG != H5_SIZEOF_LONG nerrors += test_conv_int_fp(name, TEST_NORMAL, H5T_NATIVE_LLONG, H5T_NATIVE_FLOAT); nerrors += test_conv_int_fp(name, TEST_NORMAL, H5T_NATIVE_LLONG, H5T_NATIVE_DOUBLE); +#ifdef H5_HAVE__FLOAT16 + nerrors += test_conv_int_fp(name, TEST_NORMAL, H5T_NATIVE_LLONG, H5T_NATIVE_FLOAT16); +#endif nerrors += test_conv_int_fp(name, TEST_NORMAL, H5T_NATIVE_ULLONG, H5T_NATIVE_FLOAT); nerrors += test_conv_int_fp(name, TEST_NORMAL, H5T_NATIVE_ULLONG, H5T_NATIVE_DOUBLE); +#ifdef H5_HAVE__FLOAT16 + nerrors += test_conv_int_fp(name, TEST_NORMAL, H5T_NATIVE_ULLONG, H5T_NATIVE_FLOAT16); +#endif #endif #if H5_SIZEOF_LONG_DOUBLE != H5_SIZEOF_DOUBLE @@ -4967,41 +5806,74 @@ run_fp_int_conv(const char *name) nerrors += test_conv_int_fp(name, test_values, H5T_NATIVE_FLOAT, H5T_NATIVE_SCHAR); nerrors += test_conv_int_fp(name, test_values, H5T_NATIVE_DOUBLE, H5T_NATIVE_SCHAR); +#ifdef H5_HAVE__FLOAT16 + nerrors += test_conv_int_fp(name, test_values, H5T_NATIVE_FLOAT16, H5T_NATIVE_SCHAR); +#endif nerrors += test_conv_int_fp(name, test_values, H5T_NATIVE_FLOAT, H5T_NATIVE_UCHAR); nerrors += test_conv_int_fp(name, test_values, H5T_NATIVE_DOUBLE, H5T_NATIVE_UCHAR); +#ifdef H5_HAVE__FLOAT16 + nerrors += test_conv_int_fp(name, test_values, H5T_NATIVE_FLOAT16, H5T_NATIVE_UCHAR); +#endif nerrors += test_conv_int_fp(name, test_values, H5T_NATIVE_FLOAT, H5T_NATIVE_SHORT); nerrors += test_conv_int_fp(name, test_values, H5T_NATIVE_DOUBLE, H5T_NATIVE_SHORT); +#ifdef H5_HAVE__FLOAT16 + nerrors += test_conv_int_fp(name, test_values, H5T_NATIVE_FLOAT16, H5T_NATIVE_SHORT); +#endif nerrors += test_conv_int_fp(name, test_values, H5T_NATIVE_FLOAT, H5T_NATIVE_USHORT); nerrors += test_conv_int_fp(name, test_values, H5T_NATIVE_DOUBLE, H5T_NATIVE_USHORT); +#ifdef H5_HAVE__FLOAT16 + nerrors += test_conv_int_fp(name, test_values, H5T_NATIVE_FLOAT16, H5T_NATIVE_USHORT); +#endif nerrors += test_conv_int_fp(name, test_values, H5T_NATIVE_FLOAT, H5T_NATIVE_INT); nerrors += test_conv_int_fp(name, test_values, H5T_NATIVE_DOUBLE, H5T_NATIVE_INT); +#ifdef H5_HAVE__FLOAT16 + nerrors += test_conv_int_fp(name, test_values, H5T_NATIVE_FLOAT16, H5T_NATIVE_INT); +#endif nerrors += test_conv_int_fp(name, test_values, H5T_NATIVE_FLOAT, H5T_NATIVE_UINT); nerrors += test_conv_int_fp(name, test_values, H5T_NATIVE_DOUBLE, H5T_NATIVE_UINT); +#ifdef H5_HAVE__FLOAT16 + nerrors += test_conv_int_fp(name, test_values, H5T_NATIVE_FLOAT16, H5T_NATIVE_UINT); +#endif #if H5_SIZEOF_LONG != H5_SIZEOF_INT nerrors += test_conv_int_fp(name, test_values, H5T_NATIVE_FLOAT, H5T_NATIVE_LONG); nerrors += test_conv_int_fp(name, test_values, H5T_NATIVE_DOUBLE, H5T_NATIVE_LONG); +#ifdef H5_HAVE__FLOAT16 + nerrors += test_conv_int_fp(name, test_values, H5T_NATIVE_FLOAT16, H5T_NATIVE_LONG); +#endif nerrors += test_conv_int_fp(name, test_values, H5T_NATIVE_FLOAT, H5T_NATIVE_ULONG); nerrors += test_conv_int_fp(name, test_values, H5T_NATIVE_DOUBLE, H5T_NATIVE_ULONG); +#ifdef H5_HAVE__FLOAT16 + nerrors += test_conv_int_fp(name, test_values, H5T_NATIVE_FLOAT16, H5T_NATIVE_ULONG); +#endif #endif #if H5_SIZEOF_LONG_LONG != H5_SIZEOF_LONG if (!strcmp(name, "hw")) { /* Hardware conversion */ nerrors += test_conv_int_fp(name, test_values, H5T_NATIVE_FLOAT, H5T_NATIVE_LLONG); nerrors += test_conv_int_fp(name, test_values, H5T_NATIVE_DOUBLE, H5T_NATIVE_LLONG); +#ifdef H5_HAVE__FLOAT16 + nerrors += test_conv_int_fp(name, test_values, H5T_NATIVE_FLOAT16, H5T_NATIVE_LLONG); +#endif } else { /* Software conversion */ nerrors += test_conv_int_fp(name, test_values, H5T_NATIVE_FLOAT, H5T_NATIVE_LLONG); nerrors += test_conv_int_fp(name, test_values, H5T_NATIVE_DOUBLE, H5T_NATIVE_LLONG); +#ifdef H5_HAVE__FLOAT16 + nerrors += test_conv_int_fp(name, test_values, H5T_NATIVE_FLOAT16, H5T_NATIVE_LLONG); +#endif } nerrors += test_conv_int_fp(name, test_values, H5T_NATIVE_FLOAT, H5T_NATIVE_ULLONG); nerrors += test_conv_int_fp(name, test_values, H5T_NATIVE_DOUBLE, H5T_NATIVE_ULLONG); +#ifdef H5_HAVE__FLOAT16 + nerrors += test_conv_int_fp(name, test_values, H5T_NATIVE_FLOAT16, H5T_NATIVE_ULLONG); +#endif #endif #if H5_SIZEOF_LONG_DOUBLE != H5_SIZEOF_DOUBLE |