summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rwxr-xr-xconfigure104
-rw-r--r--configure.in65
-rw-r--r--src/H5T.c4
-rw-r--r--src/H5Tconv.c4
-rw-r--r--src/H5Tpkg.h13
-rw-r--r--src/H5config.h.in4
-rw-r--r--test/dt_arith.c18
7 files changed, 203 insertions, 9 deletions
diff --git a/configure b/configure
index 4f1f8ab..176bc3e 100755
--- a/configure
+++ b/configure
@@ -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
diff --git a/src/H5T.c b/src/H5T.c
index 2a1295e..b955b40 100644
--- a/src/H5T.c
+++ b/src/H5T.c
@@ -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*/