From 10c1c557359837d97d21e966ed8286382da0d122 Mon Sep 17 00:00:00 2001 From: Jordan Henderson Date: Fri, 1 Mar 2024 20:29:45 -0600 Subject: Work around issues with MacOS 13 Add CMake status message about _Float16 test-compile program --- .github/workflows/main.yml | 1 - config/cmake/ConfigureChecks.cmake | 124 +++++---- config/cmake/ConversionTests.c | 29 +++ config/cmake/H5pubconf.h.in | 3 + configure.ac | 39 ++- src/H5T.c | 392 ++++++++++++++-------------- src/H5Tconv.c | 2 + src/H5Tpkg.h | 10 + test/dt_arith.c | 509 +++++++++++++++++++++++++++---------- 9 files changed, 722 insertions(+), 387 deletions(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 3f878b1..7a0eb69 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -36,4 +36,3 @@ jobs: name: "CMake Workflows" uses: ./.github/workflows/cmake.yml if: "!contains(github.event.head_commit.message, 'skip-ci')" - diff --git a/config/cmake/ConfigureChecks.cmake b/config/cmake/ConfigureChecks.cmake index 25de5b0..c088926 100644 --- a/config/cmake/ConfigureChecks.cmake +++ b/config/cmake/ConfigureChecks.cmake @@ -363,56 +363,6 @@ endif () HDF_CHECK_TYPE_SIZE (time_t ${HDF_PREFIX}_SIZEOF_TIME_T) #----------------------------------------------------------------------------- -# Check if _Float16 type is available -#----------------------------------------------------------------------------- -HDF_CHECK_TYPE_SIZE (_Float16 ${HDF_PREFIX}_SIZEOF__FLOAT16) -if (${HDF_PREFIX}_SIZEOF__FLOAT16) - # Ask for _Float16 support - set (CMAKE_REQUIRED_DEFINITIONS ${CMAKE_REQUIRED_DEFINITIONS} "-D__STDC_WANT_IEC_60559_TYPES_EXT__") - - # Some compilers expose the _Float16 datatype, but not the macros and - # functions used with the datatype. We need the macros for proper - # datatype conversion support. The main function we're interested in - # is fabsf16. Check for these here. - CHECK_SYMBOL_EXISTS (FLT16_EPSILON "float.h" h5_have_flt16_epsilon) - CHECK_SYMBOL_EXISTS (FLT16_MIN "float.h" h5_have_flt16_min) - CHECK_SYMBOL_EXISTS (FLT16_MAX "float.h" h5_have_flt16_max) - CHECK_SYMBOL_EXISTS (FLT16_MIN_10_EXP "float.h" h5_have_flt16_min_10_exp) - CHECK_SYMBOL_EXISTS (FLT16_MAX_10_EXP "float.h" h5_have_flt16_max_10_exp) - CHECK_SYMBOL_EXISTS (FLT16_MANT_DIG "float.h" h5_have_flt16_mant_dig) - - if (h5_have_flt16_epsilon AND h5_have_flt16_min AND - h5_have_flt16_max AND h5_have_flt16_min_10_exp AND - h5_have_flt16_max_10_exp AND h5_have_flt16_mant_dig) - # Finally, some compilers like OneAPI on MSVC appear to just be broken, - # as support for _Float16 and its macros can be detected properly, but - # then code is generated that uses the __truncsfhf2, __truncdfhf2, - # __extendhfsf2 functions, which end up being unresolved with MSVC. Let's - # try to compile a program that will generate these functions as a last - # resort for checking for _Float16 support. - message (VERBOSE "Compiling test program for _Float16 support") - try_compile ( - h5_compiled_float16_test - ${CMAKE_BINARY_DIR} - ${HDF_RESOURCES_DIR}/HDFTests.c - COMPILE_DEFINITIONS "-DCHECK_FLOAT16" - C_STANDARD 99 - ) - - if (${h5_compiled_float16_test}) - set (${HDF_PREFIX}_HAVE__FLOAT16 1) - - # Check if we can use fabsf16 - CHECK_FUNCTION_EXISTS (fabsf16 ${HDF_PREFIX}_HAVE_FABSF16) - endif () - else () - set (${HDF_PREFIX}_HAVE__FLOAT16 0) - endif () -else () - set (${HDF_PREFIX}_HAVE__FLOAT16 0) -endif () - -#----------------------------------------------------------------------------- # Extra C99 types #----------------------------------------------------------------------------- @@ -941,7 +891,8 @@ macro (H5ConversionTests TEST def msg) ${CMAKE_BINARY_DIR} ${HDF_RESOURCES_DIR}/ConversionTests.c CMAKE_FLAGS -DCOMPILE_DEFINITIONS:STRING=-D${TEST}_TEST - OUTPUT_VARIABLE OUTPUT + COMPILE_OUTPUT_VARIABLE ${TEST}_COMPILE_OUTPUT + RUN_OUTPUT_VARIABLE ${TEST}_RUN_OUTPUT ) if (${TEST}_COMPILE) if (${TEST}_RUN EQUAL "0") @@ -951,14 +902,17 @@ macro (H5ConversionTests TEST def msg) set (${TEST} "" CACHE INTERNAL ${msg}) message (VERBOSE "${msg}... no") file (APPEND ${CMAKE_BINARY_DIR}/CMakeFiles/CMakeError.log - "Test ${TEST} Run failed with the following output and exit code:\n ${OUTPUT}\n" + "Test ${TEST} Compile succeeded with the following output:\n ${${TEST}_COMPILE_OUTPUT}\n" + ) + file (APPEND ${CMAKE_BINARY_DIR}/CMakeFiles/CMakeError.log + "Test ${TEST} Run failed with exit code ${${TEST}_RUN} and with the following output:\n ${${TEST}_RUN_OUTPUT}\n" ) endif () else () set (${TEST} "" CACHE INTERNAL ${msg}) message (VERBOSE "${msg}... no") file (APPEND ${CMAKE_BINARY_DIR}/CMakeFiles/CMakeError.log - "Test ${TEST} Compile failed with the following output:\n ${OUTPUT}\n" + "Test ${TEST} Compile failed with the following output:\n ${${TEST}_COMPILE_OUTPUT}\n" ) endif () else () @@ -1020,3 +974,67 @@ H5ConversionTests (${HDF_PREFIX}_LLONG_TO_LDOUBLE_CORRECT TRUE "Checking IF corr # some long double values #----------------------------------------------------------------------------- H5ConversionTests (${HDF_PREFIX}_DISABLE_SOME_LDOUBLE_CONV FALSE "Checking IF the cpu is power9 and cannot correctly converting long double values") + +#----------------------------------------------------------------------------- +# Check if _Float16 type is available +#----------------------------------------------------------------------------- +HDF_CHECK_TYPE_SIZE (_Float16 ${HDF_PREFIX}_SIZEOF__FLOAT16) +if (${HDF_PREFIX}_SIZEOF__FLOAT16) + # Request _Float16 support + set (CMAKE_REQUIRED_DEFINITIONS ${CMAKE_REQUIRED_DEFINITIONS} "-D__STDC_WANT_IEC_60559_TYPES_EXT__") + + # Some compilers expose the _Float16 datatype, but not the macros and + # functions used with the datatype. We need the macros for proper + # datatype conversion support. The main function we're interested in + # is fabsf16. Check for these here. + CHECK_SYMBOL_EXISTS (FLT16_EPSILON "float.h" h5_have_flt16_epsilon) + CHECK_SYMBOL_EXISTS (FLT16_MIN "float.h" h5_have_flt16_min) + CHECK_SYMBOL_EXISTS (FLT16_MAX "float.h" h5_have_flt16_max) + CHECK_SYMBOL_EXISTS (FLT16_MIN_10_EXP "float.h" h5_have_flt16_min_10_exp) + CHECK_SYMBOL_EXISTS (FLT16_MAX_10_EXP "float.h" h5_have_flt16_max_10_exp) + CHECK_SYMBOL_EXISTS (FLT16_MANT_DIG "float.h" h5_have_flt16_mant_dig) + + if (h5_have_flt16_epsilon AND h5_have_flt16_min AND + h5_have_flt16_max AND h5_have_flt16_min_10_exp AND + h5_have_flt16_max_10_exp AND h5_have_flt16_mant_dig) + # Some compilers like OneAPI on MSVC appear to just be broken, as support + # for _Float16 and its macros can be detected properly, but then code is + # generated that uses the __truncsfhf2, __truncdfhf2, __extendhfsf2 functions, + # which end up being unresolved with MSVC. Let's try to compile a program + # that will generate these functions to check for _Float16 support. + message (STATUS "Compiling test program to check for _Float16 support") + try_compile ( + h5_compiled_float16_test + ${CMAKE_BINARY_DIR} + ${HDF_RESOURCES_DIR}/HDFTests.c + COMPILE_DEFINITIONS "-DCHECK_FLOAT16" + C_STANDARD 99 + ) + + if (${h5_compiled_float16_test}) + # Finally, MacOS 13 appears to have a bug specifically when converting + # long double values to _Float16. Release builds of the dt_arith test + # would cause any assignments to a _Float16 variable to be elided, + # whereas Debug builds would perform incorrect hardware conversions by + # simply chopping off all the bytes of the value except for the first 2. + # These tests pass on MacOS 14, so let's perform a quick test to check + # if the hardware conversion is done correctly. + H5ConversionTests ( + ${HDF_PREFIX}_LDOUBLE_TO_FLOAT16_CORRECT + TRUE + "Checking if correctly converting long double to _Float16 values" + ) + + set (${HDF_PREFIX}_HAVE__FLOAT16 1) + + # Check if we can use fabsf16 + CHECK_FUNCTION_EXISTS (fabsf16 ${HDF_PREFIX}_HAVE_FABSF16) + else () + message (STATUS "Failed to compile test program to check for _Float16 support") + endif () + else () + set (${HDF_PREFIX}_HAVE__FLOAT16 0) + endif () +else () + set (${HDF_PREFIX}_HAVE__FLOAT16 0) +endif () diff --git a/config/cmake/ConversionTests.c b/config/cmake/ConversionTests.c index 725f049..5a3e016 100644 --- a/config/cmake/ConversionTests.c +++ b/config/cmake/ConversionTests.c @@ -285,3 +285,32 @@ int HDF_NO_UBSAN main(void) } #endif + +#ifdef H5_LDOUBLE_TO_FLOAT16_CORRECT_TEST + +#define __STDC_WANT_IEC_60559_TYPES_EXT__ + +#include +#include +#include +#include + +int HDF_NO_UBSAN main(void) +{ + long double ld; + _Float16 half; + int ret = 1; + + ld = 32.0L; + half = 64.0f16; + + half = (_Float16)ld; + + if (fabsl(ld - (long double)half) < LDBL_EPSILON) + ret = 0; + +done: + exit(ret); +} + +#endif diff --git a/config/cmake/H5pubconf.h.in b/config/cmake/H5pubconf.h.in index 5be6dc4..5682c2a 100644 --- a/config/cmake/H5pubconf.h.in +++ b/config/cmake/H5pubconf.h.in @@ -393,6 +393,9 @@ /* Define if new-style references should be used with dimension scales */ #cmakedefine H5_DIMENSION_SCALES_WITH_NEW_REF @H5_DIMENSION_SCALES_WITH_NEW_REF@ +/* Define if your system can convert long double to _Float16 values correctly. */ +#cmakedefine H5_LDOUBLE_TO_FLOAT16_CORRECT @H5_LDOUBLE_TO_FLOAT16_CORRECT@ + /* Define if your system can convert long double to (unsigned) long long values correctly. */ #cmakedefine H5_LDOUBLE_TO_LLONG_ACCURATE @H5_LDOUBLE_TO_LLONG_ACCURATE@ diff --git a/configure.ac b/configure.ac index 2fdfbb6..7d67f2d 100644 --- a/configure.ac +++ b/configure.ac @@ -581,12 +581,11 @@ if test "$ac_cv_sizeof__Float16" != 0; then test "X$ac_cv_have_decl_FLT16_MIN_10_EXP" = "Xyes" && test "X$ac_cv_have_decl_FLT16_MAX_10_EXP" = "Xyes" && test "X$ac_cv_have_decl_FLT16_MANT_DIG" = "Xyes" ; then - # Finally, some compilers like OneAPI on MSVC appear to just be broken, - # as support for _Float16 and its macros can be detected properly, but - # then code is generated that uses the __truncsfhf2, __truncdfhf2, - # __extendhfsf2 functions, which end up being unresolved with MSVC. Let's - # try to compile a program that will generate these functions as a last - # resort for checking for _Float16 support. + # Some compilers like OneAPI on MSVC appear to just be broken, as support + # for _Float16 and its macros can be detected properly, but then code is + # generated that uses the __truncsfhf2, __truncdfhf2, __extendhfsf2 functions, + # which end up being unresolved with MSVC. Let's try to compile a program + # that will generate these functions to check for _Float16 support. AC_MSG_CHECKING([if _Float16 program can be compiled]) AC_CACHE_VAL([hdf5_cv_float16_prog_compiled], [AC_RUN_IFELSE( @@ -614,7 +613,33 @@ if test "$ac_cv_sizeof__Float16" != 0; then if test ${hdf5_cv_float16_prog_compiled} = "yes" ; then AC_MSG_RESULT([yes]) - + + # Finally, MacOS 13 appears to have a bug specifically when converting + # long double values to _Float16. Release builds of the dt_arith test + # would cause any assignments to a _Float16 variable to be elided, + # whereas Debug builds would perform incorrect hardware conversions by + # simply chopping off all the bytes of the value except for the first 2. + # These tests pass on MacOS 14, so let's perform a quick test to check + # if the hardware conversion is done correctly. + AC_MSG_CHECKING([if compiler can correctly convert long double values to _Float16]) + TEST_SRC="`(echo \"#define H5_LDOUBLE_TO_FLOAT16_CORRECT_TEST 1\"; cat $srcdir/config/cmake/ConversionTests.c)`" + if test ${ac_cv_sizeof_long_double} = 0; then + hdf5_cv_ldouble_to_float16_correct=${hdf5_cv_ldouble_to_float16_correct=no} + else + AC_CACHE_VAL([hdf5_cv_ldouble_to_float16_correct], + [AC_RUN_IFELSE( + [AC_LANG_SOURCE([$TEST_SRC])], + [hdf5_cv_ldouble_to_float16_correct=yes], [hdf5_cv_ldouble_to_float16_correct=no], [hdf5_cv_ldouble_to_float16_correct=yes])]) + fi + + if test ${hdf5_cv_ldouble_to_float16_correct} = "yes"; then + AC_DEFINE([LDOUBLE_TO_FLOAT16_CORRECT], [1], + [Define if your system can convert long double to _Float16 values correctly.]) + AC_MSG_RESULT([yes]) + else + AC_MSG_RESULT([no]) + fi + HAVE__FLOAT16="yes" # Check if we can use fabsf16 diff --git a/src/H5T.c b/src/H5T.c index a340211..ab284b6 100644 --- a/src/H5T.c +++ b/src/H5T.c @@ -398,105 +398,105 @@ H5T_order_t H5T_native_order_g = H5T_ORDER_ERROR; * If more of these are added, the new ones must be added to the list of * types to reset in H5T_term_package(). */ -hid_t H5T_IEEE_F16BE_g = FAIL; -hid_t H5T_IEEE_F16LE_g = FAIL; -hid_t H5T_IEEE_F32BE_g = FAIL; -hid_t H5T_IEEE_F32LE_g = FAIL; -hid_t H5T_IEEE_F64BE_g = FAIL; -hid_t H5T_IEEE_F64LE_g = FAIL; - -hid_t H5T_VAX_F32_g = FAIL; -hid_t H5T_VAX_F64_g = FAIL; - -hid_t H5T_STD_I8BE_g = FAIL; -hid_t H5T_STD_I8LE_g = FAIL; -hid_t H5T_STD_I16BE_g = FAIL; -hid_t H5T_STD_I16LE_g = FAIL; -hid_t H5T_STD_I32BE_g = FAIL; -hid_t H5T_STD_I32LE_g = FAIL; -hid_t H5T_STD_I64BE_g = FAIL; -hid_t H5T_STD_I64LE_g = FAIL; -hid_t H5T_STD_U8BE_g = FAIL; -hid_t H5T_STD_U8LE_g = FAIL; -hid_t H5T_STD_U16BE_g = FAIL; -hid_t H5T_STD_U16LE_g = FAIL; -hid_t H5T_STD_U32BE_g = FAIL; -hid_t H5T_STD_U32LE_g = FAIL; -hid_t H5T_STD_U64BE_g = FAIL; -hid_t H5T_STD_U64LE_g = FAIL; -hid_t H5T_STD_B8BE_g = FAIL; -hid_t H5T_STD_B8LE_g = FAIL; -hid_t H5T_STD_B16BE_g = FAIL; -hid_t H5T_STD_B16LE_g = FAIL; -hid_t H5T_STD_B32BE_g = FAIL; -hid_t H5T_STD_B32LE_g = FAIL; -hid_t H5T_STD_B64BE_g = FAIL; -hid_t H5T_STD_B64LE_g = FAIL; -hid_t H5T_STD_REF_OBJ_g = FAIL; -hid_t H5T_STD_REF_DSETREG_g = FAIL; -hid_t H5T_STD_REF_g = FAIL; - -hid_t H5T_UNIX_D32BE_g = FAIL; -hid_t H5T_UNIX_D32LE_g = FAIL; -hid_t H5T_UNIX_D64BE_g = FAIL; -hid_t H5T_UNIX_D64LE_g = FAIL; - -hid_t H5T_C_S1_g = FAIL; - -hid_t H5T_FORTRAN_S1_g = FAIL; - -hid_t H5T_NATIVE_SCHAR_g = FAIL; -hid_t H5T_NATIVE_UCHAR_g = FAIL; -hid_t H5T_NATIVE_SHORT_g = FAIL; -hid_t H5T_NATIVE_USHORT_g = FAIL; -hid_t H5T_NATIVE_INT_g = FAIL; -hid_t H5T_NATIVE_UINT_g = FAIL; -hid_t H5T_NATIVE_LONG_g = FAIL; -hid_t H5T_NATIVE_ULONG_g = FAIL; -hid_t H5T_NATIVE_LLONG_g = FAIL; -hid_t H5T_NATIVE_ULLONG_g = FAIL; -hid_t H5T_NATIVE_FLOAT16_g = FAIL; -hid_t H5T_NATIVE_FLOAT_g = FAIL; -hid_t H5T_NATIVE_DOUBLE_g = FAIL; -hid_t H5T_NATIVE_LDOUBLE_g = FAIL; -hid_t H5T_NATIVE_B8_g = FAIL; -hid_t H5T_NATIVE_B16_g = FAIL; -hid_t H5T_NATIVE_B32_g = FAIL; -hid_t H5T_NATIVE_B64_g = FAIL; -hid_t H5T_NATIVE_OPAQUE_g = FAIL; -hid_t H5T_NATIVE_HADDR_g = FAIL; -hid_t H5T_NATIVE_HSIZE_g = FAIL; -hid_t H5T_NATIVE_HSSIZE_g = FAIL; -hid_t H5T_NATIVE_HERR_g = FAIL; -hid_t H5T_NATIVE_HBOOL_g = FAIL; - -hid_t H5T_NATIVE_INT8_g = FAIL; -hid_t H5T_NATIVE_UINT8_g = FAIL; -hid_t H5T_NATIVE_INT_LEAST8_g = FAIL; -hid_t H5T_NATIVE_UINT_LEAST8_g = FAIL; -hid_t H5T_NATIVE_INT_FAST8_g = FAIL; -hid_t H5T_NATIVE_UINT_FAST8_g = FAIL; - -hid_t H5T_NATIVE_INT16_g = FAIL; -hid_t H5T_NATIVE_UINT16_g = FAIL; -hid_t H5T_NATIVE_INT_LEAST16_g = FAIL; -hid_t H5T_NATIVE_UINT_LEAST16_g = FAIL; -hid_t H5T_NATIVE_INT_FAST16_g = FAIL; -hid_t H5T_NATIVE_UINT_FAST16_g = FAIL; - -hid_t H5T_NATIVE_INT32_g = FAIL; -hid_t H5T_NATIVE_UINT32_g = FAIL; -hid_t H5T_NATIVE_INT_LEAST32_g = FAIL; -hid_t H5T_NATIVE_UINT_LEAST32_g = FAIL; -hid_t H5T_NATIVE_INT_FAST32_g = FAIL; -hid_t H5T_NATIVE_UINT_FAST32_g = FAIL; - -hid_t H5T_NATIVE_INT64_g = FAIL; -hid_t H5T_NATIVE_UINT64_g = FAIL; -hid_t H5T_NATIVE_INT_LEAST64_g = FAIL; -hid_t H5T_NATIVE_UINT_LEAST64_g = FAIL; -hid_t H5T_NATIVE_INT_FAST64_g = FAIL; -hid_t H5T_NATIVE_UINT_FAST64_g = FAIL; +hid_t H5T_IEEE_F16BE_g = H5I_INVALID_HID; +hid_t H5T_IEEE_F16LE_g = H5I_INVALID_HID; +hid_t H5T_IEEE_F32BE_g = H5I_INVALID_HID; +hid_t H5T_IEEE_F32LE_g = H5I_INVALID_HID; +hid_t H5T_IEEE_F64BE_g = H5I_INVALID_HID; +hid_t H5T_IEEE_F64LE_g = H5I_INVALID_HID; + +hid_t H5T_VAX_F32_g = H5I_INVALID_HID; +hid_t H5T_VAX_F64_g = H5I_INVALID_HID; + +hid_t H5T_STD_I8BE_g = H5I_INVALID_HID; +hid_t H5T_STD_I8LE_g = H5I_INVALID_HID; +hid_t H5T_STD_I16BE_g = H5I_INVALID_HID; +hid_t H5T_STD_I16LE_g = H5I_INVALID_HID; +hid_t H5T_STD_I32BE_g = H5I_INVALID_HID; +hid_t H5T_STD_I32LE_g = H5I_INVALID_HID; +hid_t H5T_STD_I64BE_g = H5I_INVALID_HID; +hid_t H5T_STD_I64LE_g = H5I_INVALID_HID; +hid_t H5T_STD_U8BE_g = H5I_INVALID_HID; +hid_t H5T_STD_U8LE_g = H5I_INVALID_HID; +hid_t H5T_STD_U16BE_g = H5I_INVALID_HID; +hid_t H5T_STD_U16LE_g = H5I_INVALID_HID; +hid_t H5T_STD_U32BE_g = H5I_INVALID_HID; +hid_t H5T_STD_U32LE_g = H5I_INVALID_HID; +hid_t H5T_STD_U64BE_g = H5I_INVALID_HID; +hid_t H5T_STD_U64LE_g = H5I_INVALID_HID; +hid_t H5T_STD_B8BE_g = H5I_INVALID_HID; +hid_t H5T_STD_B8LE_g = H5I_INVALID_HID; +hid_t H5T_STD_B16BE_g = H5I_INVALID_HID; +hid_t H5T_STD_B16LE_g = H5I_INVALID_HID; +hid_t H5T_STD_B32BE_g = H5I_INVALID_HID; +hid_t H5T_STD_B32LE_g = H5I_INVALID_HID; +hid_t H5T_STD_B64BE_g = H5I_INVALID_HID; +hid_t H5T_STD_B64LE_g = H5I_INVALID_HID; +hid_t H5T_STD_REF_OBJ_g = H5I_INVALID_HID; +hid_t H5T_STD_REF_DSETREG_g = H5I_INVALID_HID; +hid_t H5T_STD_REF_g = H5I_INVALID_HID; + +hid_t H5T_UNIX_D32BE_g = H5I_INVALID_HID; +hid_t H5T_UNIX_D32LE_g = H5I_INVALID_HID; +hid_t H5T_UNIX_D64BE_g = H5I_INVALID_HID; +hid_t H5T_UNIX_D64LE_g = H5I_INVALID_HID; + +hid_t H5T_C_S1_g = H5I_INVALID_HID; + +hid_t H5T_FORTRAN_S1_g = H5I_INVALID_HID; + +hid_t H5T_NATIVE_SCHAR_g = H5I_INVALID_HID; +hid_t H5T_NATIVE_UCHAR_g = H5I_INVALID_HID; +hid_t H5T_NATIVE_SHORT_g = H5I_INVALID_HID; +hid_t H5T_NATIVE_USHORT_g = H5I_INVALID_HID; +hid_t H5T_NATIVE_INT_g = H5I_INVALID_HID; +hid_t H5T_NATIVE_UINT_g = H5I_INVALID_HID; +hid_t H5T_NATIVE_LONG_g = H5I_INVALID_HID; +hid_t H5T_NATIVE_ULONG_g = H5I_INVALID_HID; +hid_t H5T_NATIVE_LLONG_g = H5I_INVALID_HID; +hid_t H5T_NATIVE_ULLONG_g = H5I_INVALID_HID; +hid_t H5T_NATIVE_FLOAT16_g = H5I_INVALID_HID; +hid_t H5T_NATIVE_FLOAT_g = H5I_INVALID_HID; +hid_t H5T_NATIVE_DOUBLE_g = H5I_INVALID_HID; +hid_t H5T_NATIVE_LDOUBLE_g = H5I_INVALID_HID; +hid_t H5T_NATIVE_B8_g = H5I_INVALID_HID; +hid_t H5T_NATIVE_B16_g = H5I_INVALID_HID; +hid_t H5T_NATIVE_B32_g = H5I_INVALID_HID; +hid_t H5T_NATIVE_B64_g = H5I_INVALID_HID; +hid_t H5T_NATIVE_OPAQUE_g = H5I_INVALID_HID; +hid_t H5T_NATIVE_HADDR_g = H5I_INVALID_HID; +hid_t H5T_NATIVE_HSIZE_g = H5I_INVALID_HID; +hid_t H5T_NATIVE_HSSIZE_g = H5I_INVALID_HID; +hid_t H5T_NATIVE_HERR_g = H5I_INVALID_HID; +hid_t H5T_NATIVE_HBOOL_g = H5I_INVALID_HID; + +hid_t H5T_NATIVE_INT8_g = H5I_INVALID_HID; +hid_t H5T_NATIVE_UINT8_g = H5I_INVALID_HID; +hid_t H5T_NATIVE_INT_LEAST8_g = H5I_INVALID_HID; +hid_t H5T_NATIVE_UINT_LEAST8_g = H5I_INVALID_HID; +hid_t H5T_NATIVE_INT_FAST8_g = H5I_INVALID_HID; +hid_t H5T_NATIVE_UINT_FAST8_g = H5I_INVALID_HID; + +hid_t H5T_NATIVE_INT16_g = H5I_INVALID_HID; +hid_t H5T_NATIVE_UINT16_g = H5I_INVALID_HID; +hid_t H5T_NATIVE_INT_LEAST16_g = H5I_INVALID_HID; +hid_t H5T_NATIVE_UINT_LEAST16_g = H5I_INVALID_HID; +hid_t H5T_NATIVE_INT_FAST16_g = H5I_INVALID_HID; +hid_t H5T_NATIVE_UINT_FAST16_g = H5I_INVALID_HID; + +hid_t H5T_NATIVE_INT32_g = H5I_INVALID_HID; +hid_t H5T_NATIVE_UINT32_g = H5I_INVALID_HID; +hid_t H5T_NATIVE_INT_LEAST32_g = H5I_INVALID_HID; +hid_t H5T_NATIVE_UINT_LEAST32_g = H5I_INVALID_HID; +hid_t H5T_NATIVE_INT_FAST32_g = H5I_INVALID_HID; +hid_t H5T_NATIVE_UINT_FAST32_g = H5I_INVALID_HID; + +hid_t H5T_NATIVE_INT64_g = H5I_INVALID_HID; +hid_t H5T_NATIVE_UINT64_g = H5I_INVALID_HID; +hid_t H5T_NATIVE_INT_LEAST64_g = H5I_INVALID_HID; +hid_t H5T_NATIVE_UINT_LEAST64_g = H5I_INVALID_HID; +hid_t H5T_NATIVE_INT_FAST64_g = H5I_INVALID_HID; +hid_t H5T_NATIVE_UINT_FAST64_g = H5I_INVALID_HID; /* * Alignment constraints for HDF5 types. Accessing objects of these @@ -1165,9 +1165,11 @@ H5T_init(void) H5T__register_int(H5T_PERS_HARD, "flt_flt16", native_float, native_float16, H5T__conv_float__Float16); status |= H5T__register_int(H5T_PERS_HARD, "dbl_flt16", native_double, native_float16, H5T__conv_double__Float16); +#ifdef H5T_CONV_INTERNAL_LDOUBLE_FLOAT16 status |= H5T__register_int(H5T_PERS_HARD, "ldbl_flt16", native_ldouble, native_float16, H5T__conv_ldouble__Float16); #endif +#endif /* from long long */ status |= @@ -1733,102 +1735,102 @@ H5T_top_term_package(void) /* Reset all the datatype IDs */ if (H5T_IEEE_F32BE_g > 0) { - H5T_IEEE_F16BE_g = FAIL; - H5T_IEEE_F16LE_g = FAIL; - H5T_IEEE_F32BE_g = FAIL; - H5T_IEEE_F32LE_g = FAIL; - H5T_IEEE_F64BE_g = FAIL; - H5T_IEEE_F64LE_g = FAIL; - - H5T_STD_I8BE_g = FAIL; - H5T_STD_I8LE_g = FAIL; - H5T_STD_I16BE_g = FAIL; - H5T_STD_I16LE_g = FAIL; - H5T_STD_I32BE_g = FAIL; - H5T_STD_I32LE_g = FAIL; - H5T_STD_I64BE_g = FAIL; - H5T_STD_I64LE_g = FAIL; - H5T_STD_U8BE_g = FAIL; - H5T_STD_U8LE_g = FAIL; - H5T_STD_U16BE_g = FAIL; - H5T_STD_U16LE_g = FAIL; - H5T_STD_U32BE_g = FAIL; - H5T_STD_U32LE_g = FAIL; - H5T_STD_U64BE_g = FAIL; - H5T_STD_U64LE_g = FAIL; - H5T_STD_B8BE_g = FAIL; - H5T_STD_B8LE_g = FAIL; - H5T_STD_B16BE_g = FAIL; - H5T_STD_B16LE_g = FAIL; - H5T_STD_B32BE_g = FAIL; - H5T_STD_B32LE_g = FAIL; - H5T_STD_B64BE_g = FAIL; - H5T_STD_B64LE_g = FAIL; - H5T_STD_REF_OBJ_g = FAIL; - H5T_STD_REF_DSETREG_g = FAIL; - H5T_STD_REF_g = FAIL; - - H5T_UNIX_D32BE_g = FAIL; - H5T_UNIX_D32LE_g = FAIL; - H5T_UNIX_D64BE_g = FAIL; - H5T_UNIX_D64LE_g = FAIL; - - H5T_C_S1_g = FAIL; - - H5T_FORTRAN_S1_g = FAIL; - - H5T_NATIVE_SCHAR_g = FAIL; - H5T_NATIVE_UCHAR_g = FAIL; - H5T_NATIVE_SHORT_g = FAIL; - H5T_NATIVE_USHORT_g = FAIL; - H5T_NATIVE_INT_g = FAIL; - H5T_NATIVE_UINT_g = FAIL; - H5T_NATIVE_LONG_g = FAIL; - H5T_NATIVE_ULONG_g = FAIL; - H5T_NATIVE_LLONG_g = FAIL; - H5T_NATIVE_ULLONG_g = FAIL; - H5T_NATIVE_FLOAT16_g = FAIL; - H5T_NATIVE_FLOAT_g = FAIL; - H5T_NATIVE_DOUBLE_g = FAIL; - H5T_NATIVE_LDOUBLE_g = FAIL; - H5T_NATIVE_B8_g = FAIL; - H5T_NATIVE_B16_g = FAIL; - H5T_NATIVE_B32_g = FAIL; - H5T_NATIVE_B64_g = FAIL; - H5T_NATIVE_OPAQUE_g = FAIL; - H5T_NATIVE_HADDR_g = FAIL; - H5T_NATIVE_HSIZE_g = FAIL; - H5T_NATIVE_HSSIZE_g = FAIL; - H5T_NATIVE_HERR_g = FAIL; - H5T_NATIVE_HBOOL_g = FAIL; - - H5T_NATIVE_INT8_g = FAIL; - H5T_NATIVE_UINT8_g = FAIL; - H5T_NATIVE_INT_LEAST8_g = FAIL; - H5T_NATIVE_UINT_LEAST8_g = FAIL; - H5T_NATIVE_INT_FAST8_g = FAIL; - H5T_NATIVE_UINT_FAST8_g = FAIL; - - H5T_NATIVE_INT16_g = FAIL; - H5T_NATIVE_UINT16_g = FAIL; - H5T_NATIVE_INT_LEAST16_g = FAIL; - H5T_NATIVE_UINT_LEAST16_g = FAIL; - H5T_NATIVE_INT_FAST16_g = FAIL; - H5T_NATIVE_UINT_FAST16_g = FAIL; - - H5T_NATIVE_INT32_g = FAIL; - H5T_NATIVE_UINT32_g = FAIL; - H5T_NATIVE_INT_LEAST32_g = FAIL; - H5T_NATIVE_UINT_LEAST32_g = FAIL; - H5T_NATIVE_INT_FAST32_g = FAIL; - H5T_NATIVE_UINT_FAST32_g = FAIL; - - H5T_NATIVE_INT64_g = FAIL; - H5T_NATIVE_UINT64_g = FAIL; - H5T_NATIVE_INT_LEAST64_g = FAIL; - H5T_NATIVE_UINT_LEAST64_g = FAIL; - H5T_NATIVE_INT_FAST64_g = FAIL; - H5T_NATIVE_UINT_FAST64_g = FAIL; + H5T_IEEE_F16BE_g = H5I_INVALID_HID; + H5T_IEEE_F16LE_g = H5I_INVALID_HID; + H5T_IEEE_F32BE_g = H5I_INVALID_HID; + H5T_IEEE_F32LE_g = H5I_INVALID_HID; + H5T_IEEE_F64BE_g = H5I_INVALID_HID; + H5T_IEEE_F64LE_g = H5I_INVALID_HID; + + H5T_STD_I8BE_g = H5I_INVALID_HID; + H5T_STD_I8LE_g = H5I_INVALID_HID; + H5T_STD_I16BE_g = H5I_INVALID_HID; + H5T_STD_I16LE_g = H5I_INVALID_HID; + H5T_STD_I32BE_g = H5I_INVALID_HID; + H5T_STD_I32LE_g = H5I_INVALID_HID; + H5T_STD_I64BE_g = H5I_INVALID_HID; + H5T_STD_I64LE_g = H5I_INVALID_HID; + H5T_STD_U8BE_g = H5I_INVALID_HID; + H5T_STD_U8LE_g = H5I_INVALID_HID; + H5T_STD_U16BE_g = H5I_INVALID_HID; + H5T_STD_U16LE_g = H5I_INVALID_HID; + H5T_STD_U32BE_g = H5I_INVALID_HID; + H5T_STD_U32LE_g = H5I_INVALID_HID; + H5T_STD_U64BE_g = H5I_INVALID_HID; + H5T_STD_U64LE_g = H5I_INVALID_HID; + H5T_STD_B8BE_g = H5I_INVALID_HID; + H5T_STD_B8LE_g = H5I_INVALID_HID; + H5T_STD_B16BE_g = H5I_INVALID_HID; + H5T_STD_B16LE_g = H5I_INVALID_HID; + H5T_STD_B32BE_g = H5I_INVALID_HID; + H5T_STD_B32LE_g = H5I_INVALID_HID; + H5T_STD_B64BE_g = H5I_INVALID_HID; + H5T_STD_B64LE_g = H5I_INVALID_HID; + H5T_STD_REF_OBJ_g = H5I_INVALID_HID; + H5T_STD_REF_DSETREG_g = H5I_INVALID_HID; + H5T_STD_REF_g = H5I_INVALID_HID; + + H5T_UNIX_D32BE_g = H5I_INVALID_HID; + H5T_UNIX_D32LE_g = H5I_INVALID_HID; + H5T_UNIX_D64BE_g = H5I_INVALID_HID; + H5T_UNIX_D64LE_g = H5I_INVALID_HID; + + H5T_C_S1_g = H5I_INVALID_HID; + + H5T_FORTRAN_S1_g = H5I_INVALID_HID; + + H5T_NATIVE_SCHAR_g = H5I_INVALID_HID; + H5T_NATIVE_UCHAR_g = H5I_INVALID_HID; + H5T_NATIVE_SHORT_g = H5I_INVALID_HID; + H5T_NATIVE_USHORT_g = H5I_INVALID_HID; + H5T_NATIVE_INT_g = H5I_INVALID_HID; + H5T_NATIVE_UINT_g = H5I_INVALID_HID; + H5T_NATIVE_LONG_g = H5I_INVALID_HID; + H5T_NATIVE_ULONG_g = H5I_INVALID_HID; + H5T_NATIVE_LLONG_g = H5I_INVALID_HID; + H5T_NATIVE_ULLONG_g = H5I_INVALID_HID; + H5T_NATIVE_FLOAT16_g = H5I_INVALID_HID; + H5T_NATIVE_FLOAT_g = H5I_INVALID_HID; + H5T_NATIVE_DOUBLE_g = H5I_INVALID_HID; + H5T_NATIVE_LDOUBLE_g = H5I_INVALID_HID; + H5T_NATIVE_B8_g = H5I_INVALID_HID; + H5T_NATIVE_B16_g = H5I_INVALID_HID; + H5T_NATIVE_B32_g = H5I_INVALID_HID; + H5T_NATIVE_B64_g = H5I_INVALID_HID; + H5T_NATIVE_OPAQUE_g = H5I_INVALID_HID; + H5T_NATIVE_HADDR_g = H5I_INVALID_HID; + H5T_NATIVE_HSIZE_g = H5I_INVALID_HID; + H5T_NATIVE_HSSIZE_g = H5I_INVALID_HID; + H5T_NATIVE_HERR_g = H5I_INVALID_HID; + H5T_NATIVE_HBOOL_g = H5I_INVALID_HID; + + H5T_NATIVE_INT8_g = H5I_INVALID_HID; + H5T_NATIVE_UINT8_g = H5I_INVALID_HID; + H5T_NATIVE_INT_LEAST8_g = H5I_INVALID_HID; + H5T_NATIVE_UINT_LEAST8_g = H5I_INVALID_HID; + H5T_NATIVE_INT_FAST8_g = H5I_INVALID_HID; + H5T_NATIVE_UINT_FAST8_g = H5I_INVALID_HID; + + H5T_NATIVE_INT16_g = H5I_INVALID_HID; + H5T_NATIVE_UINT16_g = H5I_INVALID_HID; + H5T_NATIVE_INT_LEAST16_g = H5I_INVALID_HID; + H5T_NATIVE_UINT_LEAST16_g = H5I_INVALID_HID; + H5T_NATIVE_INT_FAST16_g = H5I_INVALID_HID; + H5T_NATIVE_UINT_FAST16_g = H5I_INVALID_HID; + + H5T_NATIVE_INT32_g = H5I_INVALID_HID; + H5T_NATIVE_UINT32_g = H5I_INVALID_HID; + H5T_NATIVE_INT_LEAST32_g = H5I_INVALID_HID; + H5T_NATIVE_UINT_LEAST32_g = H5I_INVALID_HID; + H5T_NATIVE_INT_FAST32_g = H5I_INVALID_HID; + H5T_NATIVE_UINT_FAST32_g = H5I_INVALID_HID; + + H5T_NATIVE_INT64_g = H5I_INVALID_HID; + H5T_NATIVE_UINT64_g = H5I_INVALID_HID; + H5T_NATIVE_INT_LEAST64_g = H5I_INVALID_HID; + H5T_NATIVE_UINT_LEAST64_g = H5I_INVALID_HID; + H5T_NATIVE_INT_FAST64_g = H5I_INVALID_HID; + H5T_NATIVE_UINT_FAST64_g = H5I_INVALID_HID; n++; } /* end if */ diff --git a/src/H5Tconv.c b/src/H5Tconv.c index d1cc307..a6629b5 100644 --- a/src/H5Tconv.c +++ b/src/H5Tconv.c @@ -8085,6 +8085,7 @@ H5T__conv_double__Float16(hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata, size_t H5_GCC_CLANG_DIAG_ON("pedantic") } +#ifdef H5T_CONV_INTERNAL_LDOUBLE_FLOAT16 herr_t H5T__conv_ldouble__Float16(hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata, size_t nelmts, size_t buf_stride, size_t H5_ATTR_UNUSED bkg_stride, void *buf, void H5_ATTR_UNUSED *bkg) @@ -8094,6 +8095,7 @@ H5T__conv_ldouble__Float16(hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata, size_ H5T_CONV_Ff(LDOUBLE, FLOAT16, long double, H5__Float16, -FLT16_MAX, FLT16_MAX); H5_GCC_CLANG_DIAG_ON("pedantic") } +#endif herr_t H5T__conv__Float16_schar(hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata, size_t nelmts, size_t buf_stride, diff --git a/src/H5Tpkg.h b/src/H5Tpkg.h index 8f063b9..9cece45 100644 --- a/src/H5Tpkg.h +++ b/src/H5Tpkg.h @@ -143,6 +143,14 @@ #define H5T_CONV_INTERNAL_LDOUBLE_ULLONG 0 #endif +/* Define an internal macro for converting long double to _Float16. Mac OS 13 + * gives incorrect conversions that appear to be resolved in Mac OS 14. */ +#ifdef H5_HAVE__FLOAT16 +#if (H5_WANT_DATA_ACCURACY && defined(H5_LDOUBLE_TO_FLOAT16_CORRECT)) || (!H5_WANT_DATA_ACCURACY) +#define H5T_CONV_INTERNAL_LDOUBLE_FLOAT16 1 +#endif +#endif + /* Statistics about a conversion function */ struct H5T_stats_t { unsigned ncalls; /*num calls to conversion function */ @@ -861,8 +869,10 @@ H5_DLL herr_t H5T__conv_float__Float16(hid_t src_id, hid_t dst_id, H5T_cdata_t * size_t buf_stride, size_t bkg_stride, void *buf, void *bkg); H5_DLL herr_t H5T__conv_double__Float16(hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata, size_t nelmts, size_t buf_stride, size_t bkg_stride, void *buf, void *bkg); +#ifdef H5T_CONV_INTERNAL_LDOUBLE_FLOAT16 H5_DLL herr_t H5T__conv_ldouble__Float16(hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata, size_t nelmts, size_t buf_stride, size_t bkg_stride, void *buf, void *bkg); +#endif H5_DLL herr_t H5T__conv__Float16_schar(hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata, size_t nelmts, size_t buf_stride, size_t bkg_stride, void *buf, void *bkg); H5_DLL herr_t H5T__conv__Float16_uchar(hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata, size_t nelmts, diff --git a/test/dt_arith.c b/test/dt_arith.c index 65dc240..173555f 100644 --- a/test/dt_arith.c +++ b/test/dt_arith.c @@ -2855,6 +2855,308 @@ 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) { +#ifdef H5_HAVE__FLOAT16 + case FLT_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 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 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) { +#ifdef H5_HAVE__FLOAT16 + case FLT_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 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 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) { +#ifdef H5_HAVE__FLOAT16 + case FLT_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 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 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 @@ -2882,8 +3184,9 @@ 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 @@ -3156,11 +3459,31 @@ 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 @@ -3169,142 +3492,30 @@ test_conv_flt_1(const char *name, int run_test, hid_t src, hid_t dst) #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 if (FLT_LDOUBLE == dst_type) { - hw_ld = (long double)*((float *)aligned); - hw = (unsigned char *)&hw_ld; -#endif - } - else if (FLT_FLOAT16 == dst_type) { #ifdef H5_HAVE__FLOAT16 - hw_half = (H5__Float16) * ((float *)aligned); - hw = (unsigned char *)&hw_half; - - /* Suppress warning about non-standard floating-point literal suffix */ - H5_GCC_CLANG_DIAG_OFF("pedantic") - underflow = fabsf(*((float *)aligned)) < (float)FLT16_MIN; - overflow = fabsf(*((float *)aligned)) > (float)FLT16_MAX; - H5_GCC_CLANG_DIAG_ON("pedantic") -#else - assert(0 && "Should not reach this point!"); + if (FLT_FLOAT16 == src_type) { + conv_ret = test_conv_flt_1_hw_conv_from_flt16(hw_p, saved, j, dst_type); + } + else #endif - } - else - goto error; + 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 if (FLT_LDOUBLE == dst_type) { - hw_ld = (long double)*((double *)aligned); - hw = (unsigned char *)&hw_ld; -#endif - } - else if (FLT_FLOAT16 == dst_type) { -#ifdef H5_HAVE__FLOAT16 - hw_half = (H5__Float16) * ((double *)aligned); - hw = (unsigned char *)&hw_half; - - /* Suppress warning about non-standard floating-point literal suffix */ - H5_GCC_CLANG_DIAG_OFF("pedantic") - underflow = fabs(*((double *)aligned)) < (double)FLT16_MIN; - overflow = fabs(*((double *)aligned)) > (double)FLT16_MAX; - H5_GCC_CLANG_DIAG_ON("pedantic") -#else - assert(0 && "Should not reach this point!"); -#endif - } - else - goto error; -#if H5_SIZEOF_LONG_DOUBLE != H5_SIZEOF_DOUBLE + 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) { - 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 if (FLT_LDOUBLE == dst_type) { - hw_ld = *((long double *)aligned); - hw = (unsigned char *)&hw_ld; - } - else if (FLT_FLOAT16 == dst_type) { -#ifdef H5_HAVE__FLOAT16 - hw_half = (H5__Float16) * ((long double *)aligned); - hw = (unsigned char *)&hw_half; - - /* Suppress warning about non-standard floating-point literal suffix */ - H5_GCC_CLANG_DIAG_OFF("pedantic") - underflow = fabsl(*((long double *)aligned)) < (long double)FLT16_MIN; - overflow = fabsl(*((long double *)aligned)) > (long double)FLT16_MAX; - H5_GCC_CLANG_DIAG_ON("pedantic") -#else - assert(0 && "Should not reach this point!"); -#endif - } - else - goto error; -#endif + conv_ret = test_conv_flt_1_hw_conv_from_ldouble(hw_p, saved, j, dst_type); } - else if (FLT_FLOAT16 == src_type) { -#ifdef H5_HAVE__FLOAT16 - memcpy(aligned, saved + j * sizeof(H5__Float16), sizeof(H5__Float16)); - if (FLT_FLOAT == dst_type) { - hw_f = (float)*((H5__Float16 *)aligned); - hw = (unsigned char *)&hw_f; - } - else if (FLT_DOUBLE == dst_type) { - hw_d = (double)*((H5__Float16 *)aligned); - hw = (unsigned char *)&hw_d; -#if H5_SIZEOF_LONG_DOUBLE != H5_SIZEOF_DOUBLE - } - else if (FLT_LDOUBLE == dst_type) { - hw_ld = (long double)*((H5__Float16 *)aligned); - hw = (unsigned char *)&hw_ld; -#endif - } - else if (FLT_FLOAT16 == dst_type) { - hw_half = *((H5__Float16 *)aligned); - hw = (unsigned char *)&hw_half; - } - else - goto error; -#else - assert(0 && "Should not reach this point!"); #endif - } - else + + 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" * is 16 bytes, precision is 80 bits. During hardware conversion, the @@ -5324,7 +5535,19 @@ run_fp_tests(const char *name) 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 @@ -5357,7 +5580,19 @@ run_fp_tests(const char *name) 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 @@ -5389,7 +5624,19 @@ run_fp_tests(const char *name) 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 -- cgit v0.12