mirror of
https://github.com/HDFGroup/hdf5.git
synced 2024-11-27 02:10:55 +08:00
[svn-r12435] Purpose: Bug fix
Description: Mac OS 10.4 on PowerPC chip has some errors to convert (unsigned) long long to long double. When the bit sequences are 0x003ff..., 0x007fff..., 0x00ffff..., 0x01ffff..., 0x7fffff..., the converted values are twice as big as they should be. Solution: Detect the error in configure and disable the compiler conversion and test case. Platforms tested: h5committest, Mac OS 10.4, and fuss.
This commit is contained in:
parent
842895a799
commit
4dfad81062
104
configure
vendored
104
configure
vendored
@ -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`"
|
||||
|
||||
|
65
configure.in
65
configure.in
@ -3156,6 +3156,71 @@ else
|
||||
AC_MSG_RESULT([no])
|
||||
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.
|
||||
|
@ -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
|
||||
|
@ -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 */
|
||||
|
||||
|
||||
/*-------------------------------------------------------------------------
|
||||
|
13
src/H5Tpkg.h
13
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
|
||||
|
||||
|
@ -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
|
||||
|
@ -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*/
|
||||
|
Loading…
Reference in New Issue
Block a user