diff options
-rwxr-xr-x | configure | 100 | ||||
-rw-r--r-- | configure.in | 63 | ||||
-rw-r--r-- | src/H5Tpkg.h | 13 | ||||
-rw-r--r-- | src/H5config.h.in | 4 | ||||
-rw-r--r-- | test/dt_arith.c | 22 |
5 files changed, 193 insertions, 9 deletions
@@ -51683,6 +51683,106 @@ else echo "${ECHO_T}no" >&6 fi +echo "$as_me:$LINENO: checking if correctly converting long double to (unsigned) long long values" >&5 +echo $ECHO_N "checking if correctly converting long double to (unsigned) long long values... $ECHO_C" >&6 + +if test ${ac_cv_sizeof_long_double} = 0; then + hdf5_ldouble_to_llong_accurate=${hdf5_ldouble_to_llong_accurate=no} +else + if test "${hdf5_ldouble_to_llong_accurate+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test "$cross_compiling" = yes; then + { { echo "$as_me:$LINENO: error: cannot run test program while cross compiling +See \`config.log' for more details." >&5 +echo "$as_me: error: cannot run test program while cross compiling +See \`config.log' for more details." >&2;} + { (exit 1); exit 1; }; } +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + + int main(void) + { + long double ld = 20041683600089727.779961L; + long long ll; + unsigned long long ull; + unsigned char s[16]; + int ret = 0; + + if(sizeof(long double) == 16) { + /*make sure the long double type is the same as the failing type + *which has 16 bytes in size and 11 bits of exponent. If it is, + *the bit sequence should be like below. It's not + *a decent way to check but this info isn't available. */ + memcpy(s, &ld, 16); + if(s[0]==0x43 && s[1]==0x51 && s[2]==0xcc && s[3]==0xf3 && + s[4]==0x85 && s[5]==0xeb && s[6]==0xc8 && s[7]==0xa0 && + s[8]==0xbf && s[9]==0xcc && s[10]==0x2a && s[11]==0x3c) { + + /*slightly adjust the bit sequence (s[8]=0xdf). The converted + *values will go wild on Mac OS 10.4 and IRIX64 6.5.*/ + s[0]=0x43; s[1]=0x51; s[2]=0xcc; s[3]=0xf3; + s[4]=0x85; s[5]=0xeb; s[6]=0xc8; s[7]=0xa0; + s[8]=0xdf; s[9]=0xcc; s[10]=0x2a; s[11]=0x3c; + s[12]=0x3d; s[13]=0x85; s[14]=0x56; s[15]=0x20; + + memcpy(&ld, s, 16); + ll = (long long)ld; + ull = (unsigned long long)ld; + + if(ll != 20041683600089728 || ull != 20041683600089728) + ret = 1; + } + } + done: + exit(ret); + } + +_ACEOF +rm -f conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { ac_try='./conftest$ac_exeext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + hdf5_ldouble_to_llong_accurate=yes +else + echo "$as_me: program exited with status $ac_status" >&5 +echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +( exit $ac_status ) +hdf5_ldouble_to_llong_accurate=no +fi +rm -f core *.core gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext +fi +fi + +fi + +if test ${hdf5_ldouble_to_llong_accurate} = "yes"; then + +cat >>confdefs.h <<\_ACEOF +#define LDOUBLE_TO_LLONG_ACCURATE 1 +_ACEOF + + echo "$as_me:$LINENO: result: yes" >&5 +echo "${ECHO_T}yes" >&6 +else + echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6 +fi + H5_VERSION="`cut -d' ' -f3 $srcdir/README.txt | head -1`" diff --git a/configure.in b/configure.in index 7afc0fd..c8bd31d 100644 --- a/configure.in +++ b/configure.in @@ -3094,6 +3094,69 @@ else fi dnl ---------------------------------------------------------------------- +dnl Set the flag to indicate that the machine can accurately convert +dnl 'long double' to '(unsigned) long long' values. (This flag should be set for +dnl all machines, except for Mac OS 10.4 and SGI IRIX64 6.5. When the bit sequence +dnl of long double is 0x4351ccf385ebc8a0bfcc2a3c..., the values of (unsigned)long long +dnl start to go wrong on these two machines. Adjusting it higher to +dnl 0x4351ccf385ebc8a0dfcc... or 0x4351ccf385ebc8a0ffcc... will make the converted +dnl values wildly wrong. This test detects this wrong behavior and disable the test. +dnl +AC_MSG_CHECKING([if correctly converting long double to (unsigned) long long values]) + +if test ${ac_cv_sizeof_long_double} = 0; then + hdf5_ldouble_to_llong_accurate=${hdf5_ldouble_to_llong_accurate=no} +else + AC_CACHE_VAL([hdf5_ldouble_to_llong_accurate], + [AC_TRY_RUN([ + int main(void) + { + long double ld = 20041683600089727.779961L; + long long ll; + unsigned long long ull; + unsigned char s[16]; + int ret = 0; + + if(sizeof(long double) == 16) { + /*make sure the long double type is the same as the failing type + *which has 16 bytes in size and 11 bits of exponent. If it is, + *the bit sequence should be like below. It's not + *a decent way to check but this info isn't available. */ + memcpy(s, &ld, 16); + if(s[0]==0x43 && s[1]==0x51 && s[2]==0xcc && s[3]==0xf3 && + s[4]==0x85 && s[5]==0xeb && s[6]==0xc8 && s[7]==0xa0 && + s[8]==0xbf && s[9]==0xcc && s[10]==0x2a && s[11]==0x3c) { + + /*slightly adjust the bit sequence (s[8]=0xdf). The converted + *values will go wild on Mac OS 10.4 and IRIX64 6.5.*/ + s[0]=0x43; s[1]=0x51; s[2]=0xcc; s[3]=0xf3; + s[4]=0x85; s[5]=0xeb; s[6]=0xc8; s[7]=0xa0; + s[8]=0xdf; s[9]=0xcc; s[10]=0x2a; s[11]=0x3c; + s[12]=0x3d; s[13]=0x85; s[14]=0x56; s[15]=0x20; + + memcpy(&ld, s, 16); + ll = (long long)ld; + ull = (unsigned long long)ld; + + if(ll != 20041683600089728 || ull != 20041683600089728) + ret = 1; + } + } + done: + exit(ret); + } + ], [hdf5_ldouble_to_llong_accurate=yes], [hdf5_ldouble_to_llong_accurate=no],)]) +fi + +if test ${hdf5_ldouble_to_llong_accurate} = "yes"; then + AC_DEFINE([LDOUBLE_TO_LLONG_ACCURATE], [1], + [Define if your system can convert long double to (unsigned) long long values correctly.]) + AC_MSG_RESULT([yes]) +else + AC_MSG_RESULT([no]) +fi + +dnl ---------------------------------------------------------------------- dnl Set some variables for general configuration information to be saved dnl and installed with the libraries. dnl diff --git a/src/H5Tpkg.h b/src/H5Tpkg.h index 522329b..9a5ab33 100644 --- a/src/H5Tpkg.h +++ b/src/H5Tpkg.h @@ -138,10 +138,10 @@ #endif /* Define an internal macro for converting long double to long long. SGI compilers give some incorrect - * conversions. HP-UX 11.00 compiler generates floating exception. The hard conversion on Windows - * .NET 2003 has a bug and gives wrong exception value. */ + * conversions. Mac OS 10.4 gives incorrect conversions. HP-UX 11.00 compiler generates floating exception. + * The hard conversion on Windows .NET 2003 has a bug and gives wrong exception value. */ #if (H5_WANT_DATA_ACCURACY && !H5_HW_FP_TO_LLONG_NOT_WORKS && H5_LDOUBLE_TO_INTEGER_ACCURATE && \ - H5_LDOUBLE_TO_INTEGER_WORKS) || \ + H5_LDOUBLE_TO_INTEGER_WORKS && H5_LDOUBLE_TO_LLONG_ACCURATE) || \ (!H5_WANT_DATA_ACCURACY && !H5_HW_FP_TO_LLONG_NOT_WORKS && H5_LDOUBLE_TO_INTEGER_WORKS) #define H5T_CONV_INTERNAL_LDOUBLE_LLONG 1 #endif @@ -156,10 +156,11 @@ #define H5T_CONV_INTERNAL_FP_ULLONG 0 #endif -/* Define an internal macro for converting long double to all integers. SGI compilers give some incorrect - * conversions. HP-UX 11.00 compiler generates floating exception. */ +/* Define an internal macro for converting long double to unsigned long long. SGI compilers give some + * incorrect conversions. Mac OS 10.4 gives incorrect conversions. HP-UX 11.00 compiler generates + * floating exception. */ #if (H5_WANT_DATA_ACCURACY && H5_LDOUBLE_TO_INTEGER_ACCURATE && H5_LDOUBLE_TO_INTEGER_WORKS && \ - H5_FP_TO_ULLONG_ACCURATE && H5_FP_TO_ULLONG_RIGHT_MAXIMUM) || \ + H5_FP_TO_ULLONG_ACCURATE && H5_FP_TO_ULLONG_RIGHT_MAXIMUM && H5_LDOUBLE_TO_LLONG_ACCURATE) || \ (!H5_WANT_DATA_ACCURACY && H5_LDOUBLE_TO_INTEGER_WORKS) #define H5T_CONV_INTERNAL_LDOUBLE_ULLONG 1 #else diff --git a/src/H5config.h.in b/src/H5config.h.in index 15bb630..5497037 100644 --- a/src/H5config.h.in +++ b/src/H5config.h.in @@ -383,6 +383,10 @@ /* Define if your system can convert from long double to integer values. */ #undef LDOUBLE_TO_INTEGER_WORKS +/* Define if your system can convert long double to (unsigned) long long + values correctly. */ +#undef LDOUBLE_TO_LLONG_ACCURATE + /* Define if your system can convert long double to unsigned int values correctly. */ #undef LDOUBLE_TO_UINT_ACCURATE diff --git a/test/dt_arith.c b/test/dt_arith.c index 2df3fd9..5569446 100644 --- a/test/dt_arith.c +++ b/test/dt_arith.c @@ -5120,10 +5120,26 @@ run_fp_int_conv(const char *name) #endif #if H5_SIZEOF_LONG_LONG!=H5_SIZEOF_LONG && H5_SIZEOF_LONG_DOUBLE!=0 +#ifdef H5_LDOUBLE_TO_LLONG_ACCURATE nerrors += test_conv_int_fp(name, test_values, H5T_NATIVE_LDOUBLE, H5T_NATIVE_LLONG); -#ifdef H5_FP_TO_ULLONG_RIGHT_MAXIMUM +#else /*H5_LDOUBLE_TO_LLONG_ACCURATE*/ + { + char str[256]; /*string */ + + sprintf(str, "Testing %s %s -> %s conversions", + name, "long double", "long long"); + printf("%-70s", str); + SKIPPED(); +#if H5_SIZEOF_LONG_DOUBLE!=0 + HDputs(" Test skipped due to hardware conversion error."); +#else + HDputs(" Test skipped due to disabled long double."); +#endif + } +#endif /*H5_LDOUBLE_TO_LLONG_ACCURATE*/ +#if H5_FP_TO_ULLONG_RIGHT_MAXIMUM && H5_LDOUBLE_TO_LLONG_ACCURATE nerrors += test_conv_int_fp(name, test_values, H5T_NATIVE_LDOUBLE, H5T_NATIVE_ULLONG); -#else /*H5_FP_TO_ULLONG_RIGHT_MAXIMUM*/ +#else /*H5_FP_TO_ULLONG_RIGHT_MAXIMUM && H5_LDOUBLE_TO_LLONG_ACCURATE*/ { char str[256]; /*string */ @@ -5137,7 +5153,7 @@ run_fp_int_conv(const char *name) HDputs(" Test skipped due to disabled long double."); #endif } -#endif /*H5_FP_TO_ULLONG_RIGHT_MAXIMUM*/ +#endif /*H5_FP_TO_ULLONG_RIGHT_MAXIMUM && H5_LDOUBLE_TO_LLONG_ACCURATE*/ #endif #endif #else /*H5_LDOUBLE_TO_INTEGER_WORKS && H5_LDOUBLE_TO_INTEGER_ACCURATE*/ |