summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rwxr-xr-xconfigure100
-rw-r--r--configure.in63
-rw-r--r--src/H5Tpkg.h13
-rw-r--r--src/H5config.h.in4
-rw-r--r--test/dt_arith.c22
5 files changed, 193 insertions, 9 deletions
diff --git a/configure b/configure
index ec9fb85..78468ad 100755
--- a/configure
+++ b/configure
@@ -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*/