diff options
-rwxr-xr-x | configure | 104 | ||||
-rw-r--r-- | configure.in | 65 | ||||
-rw-r--r-- | src/H5T.c | 4 | ||||
-rw-r--r-- | src/H5Tconv.c | 4 | ||||
-rw-r--r-- | src/H5Tpkg.h | 13 | ||||
-rw-r--r-- | src/H5config.h.in | 4 | ||||
-rw-r--r-- | test/dt_arith.c | 18 |
7 files changed, 203 insertions, 9 deletions
@@ -51783,6 +51783,110 @@ else echo "${ECHO_T}no" >&6 fi +echo "$as_me:$LINENO: checking if correctly converting (unsigned) long long to long double values" >&5 +echo $ECHO_N "checking if correctly converting (unsigned) long long to long double values... $ECHO_C" >&6 + +if test ${ac_cv_sizeof_long_double} = 0; then + hdf5_llong_to_ldouble_correct=${hdf5_llong_to_ldouble_correct=no} +else + if test "${hdf5_llong_to_ldouble_correct+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; + long long ll; + unsigned long long ull; + unsigned char s[16]; + int flag=0, ret=0; + + /*Determine if long double has 16 byte in size, 11 bit exponent, and + *the bias is 0x3ff */ + if(sizeof(long double) == 16) { + ld = 1.0L; + memcpy(s, &ld, 16); + if(s[0]==0x3f && s[1]==0xf0 && s[2]==0x00 && s[3]==0x00 && + s[4]==0x00 && s[5]==0x00 && s[6]==0x00 && s[7]==0x00) + flag = 1; + } + + if(flag==1 && sizeof(long long)==8) { + ll = 0x01ffffffffffffffLL; + ld = (long double)ll; + memcpy(s, &ld, 16); + /*Check if the bit sequence is as supposed to be*/ + if(s[0]!=0x43 || s[1]!=0x7f || s[2]!=0xff || s[3]!=0xff || + s[4]!=0xff || s[5]!=0xff || s[6]!=0xff || s[7]!=0xff || + s[8]!=0xf0 || s[9]!=0x00 || s[10]!=0x00 || s[11]!=0x00) + ret = 1; + } + if(flag==1 && sizeof(unsigned long long)==8) { + ull = 0x01ffffffffffffffULL; + ld = (long double)ull; + memcpy(s, &ld, 16); + if(s[0]!=0x43 || s[1]!=0x7f || s[2]!=0xff || s[3]!=0xff || + s[4]!=0xff || s[5]!=0xff || s[6]!=0xff || s[7]!=0xff || + s[8]!=0xf0 || s[9]!=0x00 || s[10]!=0x00 || s[11]!=0x00) + 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_llong_to_ldouble_correct=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_llong_to_ldouble_correct=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_llong_to_ldouble_correct} = "yes"; then + +cat >>confdefs.h <<\_ACEOF +#define LLONG_TO_LDOUBLE_CORRECT 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 358b5ce..e70346d 100644 --- a/configure.in +++ b/configure.in @@ -3157,6 +3157,71 @@ else fi dnl ---------------------------------------------------------------------- +dnl Set the flag to indicate that the machine can accurately convert +dnl '(unsigned) long long' to 'long double' values. (This flag should be set for +dnl all machines, except for Mac OS 10.4, when the bit sequences are 003fff..., +dnl 007fff..., 00ffff..., 01ffff..., ..., 7fffff..., the converted values are twice +dnl as big as they should be. +dnl +AC_MSG_CHECKING([if correctly converting (unsigned) long long to long double values]) + +if test ${ac_cv_sizeof_long_double} = 0; then + hdf5_llong_to_ldouble_correct=${hdf5_llong_to_ldouble_correct=no} +else + AC_CACHE_VAL([hdf5_llong_to_ldouble_correct], + [AC_TRY_RUN([ + int main(void) + { + long double ld; + long long ll; + unsigned long long ull; + unsigned char s[16]; + int flag=0, ret=0; + + /*Determine if long double has 16 byte in size, 11 bit exponent, and + *the bias is 0x3ff */ + if(sizeof(long double) == 16) { + ld = 1.0L; + memcpy(s, &ld, 16); + if(s[0]==0x3f && s[1]==0xf0 && s[2]==0x00 && s[3]==0x00 && + s[4]==0x00 && s[5]==0x00 && s[6]==0x00 && s[7]==0x00) + flag = 1; + } + + if(flag==1 && sizeof(long long)==8) { + ll = 0x01ffffffffffffffLL; + ld = (long double)ll; + memcpy(s, &ld, 16); + /*Check if the bit sequence is as supposed to be*/ + if(s[0]!=0x43 || s[1]!=0x7f || s[2]!=0xff || s[3]!=0xff || + s[4]!=0xff || s[5]!=0xff || s[6]!=0xff || s[7]!=0xff || + s[8]!=0xf0 || s[9]!=0x00 || s[10]!=0x00 || s[11]!=0x00) + ret = 1; + } + if(flag==1 && sizeof(unsigned long long)==8) { + ull = 0x01ffffffffffffffULL; + ld = (long double)ull; + memcpy(s, &ld, 16); + if(s[0]!=0x43 || s[1]!=0x7f || s[2]!=0xff || s[3]!=0xff || + s[4]!=0xff || s[5]!=0xff || s[6]!=0xff || s[7]!=0xff || + s[8]!=0xf0 || s[9]!=0x00 || s[10]!=0x00 || s[11]!=0x00) + ret = 1; + } + done: + exit(ret); + } + ], [hdf5_llong_to_ldouble_correct=yes], [hdf5_llong_to_ldouble_correct=no],)]) +fi + +if test ${hdf5_llong_to_ldouble_correct} = "yes"; then + AC_DEFINE([LLONG_TO_LDOUBLE_CORRECT], [1], + [Define if your system can convert (unsigned) long long to long double 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 @@ -1208,9 +1208,9 @@ H5T_init_interface(void) /* From long long to floats */ status |= H5T_register(H5T_PERS_HARD, "llong_flt", native_llong, native_float, H5T_conv_llong_float, H5AC_dxpl_id, FALSE); status |= H5T_register(H5T_PERS_HARD, "llong_dbl", native_llong, native_double, H5T_conv_llong_double, H5AC_dxpl_id, FALSE); -#if H5T_CONV_INTERNAL_INTEGER_LDOUBLE +#if H5T_CONV_INTERNAL_LLONG_LDOUBLE status |= H5T_register(H5T_PERS_HARD, "llong_ldbl", native_llong, native_ldouble, H5T_conv_llong_ldouble, H5AC_dxpl_id, FALSE); -#endif /* H5T_CONV_INTERNAL_INTEGER_LDOUBLE */ +#endif /* H5T_CONV_INTERNAL_LLONG_LDOUBLE */ /* From unsigned long long to floats */ #if H5T_CONV_INTERNAL_ULLONG_FP diff --git a/src/H5Tconv.c b/src/H5Tconv.c index c05b3c1..dc56c30 100644 --- a/src/H5Tconv.c +++ b/src/H5Tconv.c @@ -8343,7 +8343,7 @@ done: * *------------------------------------------------------------------------- */ -#if H5T_CONV_INTERNAL_INTEGER_LDOUBLE +#if H5T_CONV_INTERNAL_LLONG_LDOUBLE herr_t H5T_conv_llong_ldouble (hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata, size_t nelmts, size_t buf_stride, @@ -8359,7 +8359,7 @@ H5T_conv_llong_ldouble (hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata, done: FUNC_LEAVE_NOAPI(ret_value); } -#endif /* H5T_CONV_INTERNAL_INTEGER_LDOUBLE */ +#endif /* H5T_CONV_INTERNAL_LLONG_LDOUBLE */ /*------------------------------------------------------------------------- diff --git a/src/H5Tpkg.h b/src/H5Tpkg.h index 9a5ab33..ee0939e 100644 --- a/src/H5Tpkg.h +++ b/src/H5Tpkg.h @@ -99,6 +99,13 @@ #define H5T_CONV_INTERNAL_ULONG_LDOUBLE 1 #endif +/* Define an internal macro for converting long long to long double. Mac OS 10.4 gives some + * incorrect conversions. */ +#if (H5_WANT_DATA_ACCURACY && H5_INTEGER_TO_LDOUBLE_ACCURATE && H5_LLONG_TO_LDOUBLE_CORRECT) || \ + (!H5_WANT_DATA_ACCURACY) +#define H5T_CONV_INTERNAL_LLONG_LDOUBLE 1 +#endif + /* Define an internal macro for converting unsigned long long to floating numbers. SGI compilers give * some incorect conversion. 64-bit Solaris does different rounding. Windows Visual Studio 6 does * not support unsigned long long. */ @@ -110,9 +117,11 @@ /* Define an internal macro for converting unsigned long long to long double. SGI compilers give * some incorect conversion. 64-bit Solaris does different rounding. Windows Visual Studio 6 does * not support unsigned long long. For FreeBSD(sleipnir), the last 2 bytes of mantissa are lost when - * compiler tries to do the conversion. For Cygwin, compiler doesn't do rounding correctly. */ + * compiler tries to do the conversion. For Cygwin, compiler doesn't do rounding correctly. + * Mac OS 10.4 gives some incorrect result. */ #if (H5_WANT_DATA_ACCURACY && H5_ULLONG_TO_FP_CAST_WORKS && H5_ULONG_TO_FP_BOTTOM_BIT_ACCURATE && \ - H5_ULLONG_TO_LDOUBLE_PRECISION) || (!H5_WANT_DATA_ACCURACY && H5_ULLONG_TO_FP_CAST_WORKS) + H5_ULLONG_TO_LDOUBLE_PRECISION && H5_LLONG_TO_LDOUBLE_CORRECT) || (!H5_WANT_DATA_ACCURACY && \ + H5_ULLONG_TO_FP_CAST_WORKS) #define H5T_CONV_INTERNAL_ULLONG_LDOUBLE 1 #endif diff --git a/src/H5config.h.in b/src/H5config.h.in index 5497037..86e30f2 100644 --- a/src/H5config.h.in +++ b/src/H5config.h.in @@ -394,6 +394,10 @@ /* Define if your system can compile long long to floating-point casts. */ #undef LLONG_TO_FP_CAST_WORKS +/* Define if your system can convert (unsigned) long long to long double + values correctly. */ +#undef LLONG_TO_LDOUBLE_CORRECT + /* Define if your system can handle complicated MPI derived datatype correctly. */ #undef MPI_COMPLEX_DERIVED_DATATYPE_WORKS diff --git a/test/dt_arith.c b/test/dt_arith.c index 5569446..dc12696 100644 --- a/test/dt_arith.c +++ b/test/dt_arith.c @@ -4945,10 +4945,22 @@ run_int_fp_conv(const char *name) nerrors += test_conv_int_fp(name, TEST_NORMAL, H5T_NATIVE_ULONG, H5T_NATIVE_LDOUBLE); #endif #if H5_SIZEOF_LONG_LONG!=H5_SIZEOF_LONG +#if H5_LLONG_TO_LDOUBLE_CORRECT nerrors += test_conv_int_fp(name, TEST_NORMAL, H5T_NATIVE_LLONG, H5T_NATIVE_LDOUBLE); -#if H5_ULLONG_TO_FP_CAST_WORKS && H5_ULLONG_TO_LDOUBLE_PRECISION +#else /* H5_LLONG_TO_LDOUBLE_CORRECT */ + { + char str[256]; /*hello string */ + + sprintf(str, "Testing %s %s -> %s conversions", + name, "long long", "long double"); + printf("%-70s", str); + SKIPPED(); + HDputs(" Test skipped due to compiler error in handling conversion."); + } +#endif /* H5_LLONG_TO_LDOUBLE_CORRECT */ +#if H5_ULLONG_TO_FP_CAST_WORKS && H5_ULLONG_TO_LDOUBLE_PRECISION && H5_LLONG_TO_LDOUBLE_CORRECT nerrors += test_conv_int_fp(name, TEST_NORMAL, H5T_NATIVE_ULLONG, H5T_NATIVE_LDOUBLE); -#else /* H5_ULLONG_TO_FP_CAST_WORKS && H5_ULLONG_TO_LDOUBLE_PRECISION */ +#else /* H5_ULLONG_TO_FP_CAST_WORKS && H5_ULLONG_TO_LDOUBLE_PRECISION && H5_LLONG_TO_LDOUBLE_CORRECT */ { char str[256]; /*hello string */ @@ -4958,7 +4970,7 @@ run_int_fp_conv(const char *name) SKIPPED(); HDputs(" Test skipped due to compiler not handling conversion."); } -#endif /* H5_ULLONG_TO_FP_CAST_WORKS && H5_ULLONG_TO_LDOUBLE_PRECISION */ +#endif /* H5_ULLONG_TO_FP_CAST_WORKS && H5_ULLONG_TO_LDOUBLE_PRECISION && H5_LLONG_TO_LDOUBLE_CORRECT */ #endif #endif #else /*H5_INTEGER_TO_LDOUBLE_ACCURATE*/ |