From ac5a796db2b3b35a74b69fc957fc020d42adf6ef Mon Sep 17 00:00:00 2001
From: Albert Cheng <acheng@hdfgroup.org>
Date: Fri, 24 Jul 2015 02:04:52 -0500
Subject: [svn-r27428] Bug fix: DAILYTEST-170 Description:     XL compilers in
 ostrich (PowerPC64 linux) fail in test/dt_arith     because of the removal of
 the LLONG_TO_LDOUBLE_CORRECT (removed in     r26625) and
 LDOUBLE_TO_LLONG_ACCURATE (removed in r26623).

Solution:
    Reverse revisions
	r26623: bring back LDOUBLE_TO_LLONG_ACCURATE configure macro
	r26625: bring back LLONG_TO_LDOUBLE_CORRECT configure macro
	r26627: bring back WANT_DATA_ACCURACY configure macro which is
	    used together with the above two macros. This also brings
	    back the enable-dconv-accuracy configure option.

Tested:
    h5committested.
    Also tested in ostrich using the XL compilers.
---
 config/cmake/ConfigureChecks.cmake |  30 ++++++
 config/cmake/ConversionTests.c     |  82 ++++++++++++++
 config/cmake/H5pubconf.h.in        |  11 ++
 configure                          | 214 +++++++++++++++++++++++++++++++++++++
 configure.ac                       | 153 ++++++++++++++++++++++++++
 release_docs/INSTALL_CMake.txt     |   1 +
 src/H5T.c                          |   8 ++
 src/H5Tconv.c                      |   8 ++
 src/H5Tpkg.h                       |  33 ++++++
 src/H5config.h.in                  |  11 ++
 test/dt_arith.c                    |  56 ++++++++++
 11 files changed, 607 insertions(+)

diff --git a/config/cmake/ConfigureChecks.cmake b/config/cmake/ConfigureChecks.cmake
index e223553..09f1caf 100644
--- a/config/cmake/ConfigureChecks.cmake
+++ b/config/cmake/ConfigureChecks.cmake
@@ -33,6 +33,18 @@ endif (HDF5_METADATA_TRACE_FILE)
 MARK_AS_ADVANCED (HDF5_METADATA_TRACE_FILE)
 
 # ----------------------------------------------------------------------
+# Decide whether the data accuracy has higher priority during data
+# conversions.  If not, some hard conversions will still be prefered even
+# though the data may be wrong (for example, some compilers don't
+# support denormalized floating values) to maximize speed.
+#
+option (HDF5_WANT_DATA_ACCURACY "IF data accuracy is guaranteed during data conversions" ON)
+if (HDF5_WANT_DATA_ACCURACY)
+  set (H5_WANT_DATA_ACCURACY 1)
+endif (HDF5_WANT_DATA_ACCURACY)
+MARK_AS_ADVANCED (HDF5_WANT_DATA_ACCURACY)
+
+# ----------------------------------------------------------------------
 # Decide whether the presence of user's exception handling functions is
 # checked and data conversion exceptions are returned.  This is mainly
 # for the speed optimization of hard conversions.  Soft conversions can
@@ -220,6 +232,24 @@ H5ConversionTests (H5_LDOUBLE_TO_LONG_SPECIAL  "Checking IF your system converts
 #
 H5ConversionTests (H5_LONG_TO_LDOUBLE_SPECIAL "Checking IF your system can convert (unsigned) long to long double values with special algorithm")
 # ----------------------------------------------------------------------
+# Set the flag to indicate that the machine can accurately convert
+# 'long double' to '(unsigned) long long' values.  (This flag should be set for
+# all machines, except for Mac OS 10.4 and SGI IRIX64 6.5.  When the bit sequence
+# of long double is 0x4351ccf385ebc8a0bfcc2a3c..., the values of (unsigned)long long
+# start to go wrong on these two machines.  Adjusting it higher to
+# 0x4351ccf385ebc8a0dfcc... or 0x4351ccf385ebc8a0ffcc... will make the converted
+# values wildly wrong.  This test detects this wrong behavior and disable the test.
+#
+H5ConversionTests (H5_LDOUBLE_TO_LLONG_ACCURATE "Checking IF correctly converting long double to (unsigned) long long values")
+# ----------------------------------------------------------------------
+# Set the flag to indicate that the machine can accurately convert
+# '(unsigned) long long' to 'long double' values.  (This flag should be set for
+# all machines, except for Mac OS 10.4, when the bit sequences are 003fff...,
+# 007fff..., 00ffff..., 01ffff..., ..., 7fffff..., the converted values are twice
+# as big as they should be.
+#
+H5ConversionTests (H5_LLONG_TO_LDOUBLE_CORRECT "Checking IF correctly converting (unsigned) long long to long double values")
+# ----------------------------------------------------------------------
 # Check if pointer alignments are enforced
 #
 H5ConversionTests (H5_NO_ALIGNMENT_RESTRICTIONS "Checking IF alignment restrictions are strictly enforced")
diff --git a/config/cmake/ConversionTests.c b/config/cmake/ConversionTests.c
index cd2e8bb..d964bf8 100644
--- a/config/cmake/ConversionTests.c
+++ b/config/cmake/ConversionTests.c
@@ -116,6 +116,88 @@ done:
 
 #endif
 
+#ifdef H5_LDOUBLE_TO_LLONG_ACCURATE_TEST
+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);
+}
+#endif
+
+#ifdef H5_LLONG_TO_LDOUBLE_CORRECT_TEST
+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);
+}
+#endif
+
 #ifdef H5_NO_ALIGNMENT_RESTRICTIONS_TEST
 
 #include <stdlib.h>
diff --git a/config/cmake/H5pubconf.h.in b/config/cmake/H5pubconf.h.in
index fcbdbd5..31bcc08 100644
--- a/config/cmake/H5pubconf.h.in
+++ b/config/cmake/H5pubconf.h.in
@@ -398,10 +398,18 @@
 /* Define if HDF5's high-level library headers should be included in hdf5.h */
 #cmakedefine H5_INCLUDE_HL @H5_INCLUDE_HL@
 
+/* Define if your system can convert long double to (unsigned) long long
+   values correctly. */
+#cmakedefine H5_LDOUBLE_TO_LLONG_ACCURATE @H5_LDOUBLE_TO_LLONG_ACCURATE@
+
 /* Define if your system converts long double to (unsigned) long values with
    special algorithm. */
 #cmakedefine H5_LDOUBLE_TO_LONG_SPECIAL @H5_LDOUBLE_TO_LONG_SPECIAL@
 
+/* Define if your system can convert (unsigned) long long to long double
+   values correctly. */
+#cmakedefine H5_LLONG_TO_LDOUBLE_CORRECT @H5_LLONG_TO_LDOUBLE_CORRECT@
+
 /* Define if your system can convert (unsigned) long to long double values
    with special algorithm. */
 #cmakedefine H5_LONG_TO_LDOUBLE_SPECIAL @H5_LONG_TO_LDOUBLE_SPECIAL@
@@ -606,6 +614,9 @@
 /* Version number of package */
 #define H5_VERSION "@HDF5_PACKAGE_VERSION_STRING@"
 
+/* Data accuracy is prefered to speed during data conversions */
+#cmakedefine H5_WANT_DATA_ACCURACY @H5_WANT_DATA_ACCURACY@
+
 /* Check exception handling functions during data conversions */
 #cmakedefine H5_WANT_DCONV_EXCEPTION @H5_WANT_DCONV_EXCEPTION@
 
diff --git a/configure b/configure
index 00dbf24..2c3ddb9 100755
--- a/configure
+++ b/configure
@@ -911,6 +911,7 @@ with_mpe
 enable_direct_vfd
 with_default_plugindir
 enable_dconv_exception
+enable_dconv_accuracy
 enable_build_all
 enable_deprecated_symbols
 with_default_api_version
@@ -1608,6 +1609,8 @@ Optional Features:
   --enable-dconv-exception
                           if exception handling functions is checked during
                           data conversions [default=yes]
+  --enable-dconv-accuracy if data accuracy is guaranteed during data
+                          conversions [default=yes]
   --enable-build-all      Build helper programs that only developers should
                           need [default=no]
   --enable-deprecated-symbols
@@ -27477,6 +27480,33 @@ $as_echo "no" >&6; }
 fi
 
 ## ----------------------------------------------------------------------
+## Decide whether the data accuracy has higher priority during data
+## conversions.  If not, some hard conversions will still be prefered even
+## though the data may be wrong (for example, some compilers don't
+## support denormalized floating values) to maximize speed.
+##
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether data accuracy is guaranteed during data conversions" >&5
+$as_echo_n "checking whether data accuracy is guaranteed during data conversions... " >&6; }
+# Check whether --enable-dconv-accuracy was given.
+if test "${enable_dconv_accuracy+set}" = set; then :
+  enableval=$enable_dconv_accuracy; DATA_ACCURACY=$enableval
+else
+  DATA_ACCURACY=yes
+fi
+
+
+if test "$DATA_ACCURACY" = "yes"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+
+$as_echo "#define WANT_DATA_ACCURACY 1" >>confdefs.h
+
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+## ----------------------------------------------------------------------
 ## Set the flag to indicate that the machine has window style pathname,
 ## that is, "drive-letter:\" (e.g. "C:") or "drive-letter:/" (e.g. "C:/").
 ## (This flag should be _unset_ for all machines, except for Windows, where
@@ -27740,6 +27770,190 @@ $as_echo "no" >&6; }
 fi
 
 ## ----------------------------------------------------------------------
+## Set the flag to indicate that the machine can accurately convert
+## 'long double' to '(unsigned) long long' values.  (This flag should
+## be set for all machines, except for Mac OS 10.4, SGI IRIX64 6.5 and
+## Powerpc Linux using XL compilers.
+## When the bit sequence of long double is 0x4351ccf385ebc8a0bfcc2a3c...,
+## the values of (unsigned)long long start to go wrong on these
+## two machines.  Adjusting it higher to 0x4351ccf385ebc8a0dfcc... or
+## 0x4351ccf385ebc8a0ffcc... will make the converted values wildly wrong.
+## This test detects this wrong behavior and disable the test.
+##
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking if correctly converting long double to (unsigned) long long values" >&5
+$as_echo_n "checking if correctly converting long double to (unsigned) long long values... " >&6; }
+
+if test ${ac_cv_sizeof_long_double} = 0; then
+   hdf5_cv_ldouble_to_llong_accurate=${hdf5_cv_ldouble_to_llong_accurate=no}
+else
+   if ${hdf5_cv_ldouble_to_llong_accurate+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test "$cross_compiling" = yes; then :
+  { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error $? "cannot run test program while cross compiling
+See \`config.log' for more details" "$LINENO" 5; }
+else
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* 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
+if ac_fn_c_try_run "$LINENO"; then :
+  hdf5_cv_ldouble_to_llong_accurate=yes
+else
+  hdf5_cv_ldouble_to_llong_accurate=no
+fi
+rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \
+  conftest.$ac_objext conftest.beam conftest.$ac_ext
+fi
+
+fi
+
+fi
+
+if test ${hdf5_cv_ldouble_to_llong_accurate} = "yes"; then
+
+$as_echo "#define LDOUBLE_TO_LLONG_ACCURATE 1" >>confdefs.h
+
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+## ----------------------------------------------------------------------
+## Set the flag to indicate that the machine can accurately convert
+## '(unsigned) long long' to 'long double' values.  (This flag should be
+## set for all machines, except for Mac OS 10.4 and Powerpc Linux using
+## XL compilers.
+## When the bit sequences are 003fff..., 007fff..., 00ffff..., 01ffff...,
+## ..., 7fffff..., the converted values are twice as big as they should be.
+##
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking if correctly converting (unsigned) long long to long double values" >&5
+$as_echo_n "checking if correctly converting (unsigned) long long to long double values... " >&6; }
+
+if test ${ac_cv_sizeof_long_double} = 0; then
+   hdf5_cv_llong_to_ldouble_correct=${hdf5_cv_llong_to_ldouble_correct=no}
+else
+   if ${hdf5_cv_llong_to_ldouble_correct+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test "$cross_compiling" = yes; then :
+  { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error $? "cannot run test program while cross compiling
+See \`config.log' for more details" "$LINENO" 5; }
+else
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* 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
+if ac_fn_c_try_run "$LINENO"; then :
+  hdf5_cv_llong_to_ldouble_correct=yes
+else
+  hdf5_cv_llong_to_ldouble_correct=no
+fi
+rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \
+  conftest.$ac_objext conftest.beam conftest.$ac_ext
+fi
+
+fi
+
+fi
+
+if test ${hdf5_cv_llong_to_ldouble_correct} = "yes"; then
+
+$as_echo "#define LLONG_TO_LDOUBLE_CORRECT 1" >>confdefs.h
+
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+## ----------------------------------------------------------------------
 ## Set some variables for general configuration information to be saved
 ## and installed with the libraries (used to generate libhdf5.settings).
 ##
diff --git a/configure.ac b/configure.ac
index 5dd93b4..5418f28 100644
--- a/configure.ac
+++ b/configure.ac
@@ -2269,6 +2269,27 @@ else
 fi
 
 ## ----------------------------------------------------------------------
+## Decide whether the data accuracy has higher priority during data
+## conversions.  If not, some hard conversions will still be prefered even
+## though the data may be wrong (for example, some compilers don't 
+## support denormalized floating values) to maximize speed.
+## 
+AC_MSG_CHECKING([whether data accuracy is guaranteed during data conversions])
+AC_ARG_ENABLE([dconv-accuracy],
+              [AS_HELP_STRING([--enable-dconv-accuracy],
+                              [if data accuracy is guaranteed during 
+                              data conversions [default=yes]])],
+              [DATA_ACCURACY=$enableval], [DATA_ACCURACY=yes])
+
+if test "$DATA_ACCURACY" = "yes"; then
+  AC_MSG_RESULT([yes])
+  AC_DEFINE([WANT_DATA_ACCURACY], [1],
+            [Data accuracy is prefered to speed during data conversions])
+else
+  AC_MSG_RESULT([no])
+fi
+
+## ----------------------------------------------------------------------
 ## Set the flag to indicate that the machine has window style pathname,
 ## that is, "drive-letter:\" (e.g. "C:") or "drive-letter:/" (e.g. "C:/").
 ## (This flag should be _unset_ for all machines, except for Windows, where
@@ -2448,6 +2469,138 @@ else
 fi
 
 ## ----------------------------------------------------------------------
+## Set the flag to indicate that the machine can accurately convert
+## 'long double' to '(unsigned) long long' values.  (This flag should
+## be set for all machines, except for Mac OS 10.4, SGI IRIX64 6.5 and
+## Powerpc Linux using XL compilers.
+## When the bit sequence of long double is 0x4351ccf385ebc8a0bfcc2a3c...,
+## the values of (unsigned)long long start to go wrong on these
+## two machines.  Adjusting it higher to 0x4351ccf385ebc8a0dfcc... or
+## 0x4351ccf385ebc8a0ffcc... will make the converted values wildly wrong.
+## This test detects this wrong behavior and disable the test.
+##
+AC_MSG_CHECKING([if correctly converting long double to (unsigned) long long values])
+
+if test ${ac_cv_sizeof_long_double} = 0; then
+   hdf5_cv_ldouble_to_llong_accurate=${hdf5_cv_ldouble_to_llong_accurate=no}
+else
+   AC_CACHE_VAL([hdf5_cv_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_cv_ldouble_to_llong_accurate=yes], [hdf5_cv_ldouble_to_llong_accurate=no],)])
+fi
+
+if test ${hdf5_cv_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
+
+
+## ----------------------------------------------------------------------
+## Set the flag to indicate that the machine can accurately convert
+## '(unsigned) long long' to 'long double' values.  (This flag should be
+## set for all machines, except for Mac OS 10.4 and Powerpc Linux using
+## XL compilers.
+## When the bit sequences are 003fff..., 007fff..., 00ffff..., 01ffff...,
+## ..., 7fffff..., the converted values are twice as big as they should be.
+##
+AC_MSG_CHECKING([if correctly converting (unsigned) long long to long double values])
+
+if test ${ac_cv_sizeof_long_double} = 0; then
+   hdf5_cv_llong_to_ldouble_correct=${hdf5_cv_llong_to_ldouble_correct=no}
+else
+   AC_CACHE_VAL([hdf5_cv_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_cv_llong_to_ldouble_correct=yes], [hdf5_cv_llong_to_ldouble_correct=no],)])
+fi
+
+if test ${hdf5_cv_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
+
+## ----------------------------------------------------------------------
 ## Set some variables for general configuration information to be saved
 ## and installed with the libraries (used to generate libhdf5.settings).
 ##
diff --git a/release_docs/INSTALL_CMake.txt b/release_docs/INSTALL_CMake.txt
index 7f67eb2..7a98bef 100644
--- a/release_docs/INSTALL_CMake.txt
+++ b/release_docs/INSTALL_CMake.txt
@@ -591,6 +591,7 @@ HDF5_STRICT_FORMAT_CHECKS      "Whether to perform strict file format checks"
 HDF5_TEST_VFD                  "Execute tests with different VFDs"                            OFF
 HDF5_USE_16_API_DEFAULT        "Use the HDF5 1.6.x API by default"                            OFF
 HDF5_USE_FOLDERS               "Enable folder grouping of projects in IDEs."                  OFF
+HDF5_WANT_DATA_ACCURACY        "IF data accuracy is guaranteed during data conversions"       ON
 HDF5_WANT_DCONV_EXCEPTION      "exception handling functions is checked during data conversions" ON
 HDF5_ENABLE_THREADSAFE         "Enable Threadsafety"                                          OFF
 if (APPLE) 
diff --git a/src/H5T.c b/src/H5T.c
index 906061e..5f6c8e3 100644
--- a/src/H5T.c
+++ b/src/H5T.c
@@ -1222,12 +1222,16 @@ 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_ind_dxpl_id, FALSE);
     status |= H5T_register(H5T_PERS_HARD, "llong_dbl", native_llong, native_double, H5T__conv_llong_double, H5AC_ind_dxpl_id, FALSE);
+#ifdef H5T_CONV_INTERNAL_LLONG_LDOUBLE
     status |= H5T_register(H5T_PERS_HARD, "llong_ldbl", native_llong, native_ldouble, H5T__conv_llong_ldouble, H5AC_ind_dxpl_id, FALSE);
+#endif /* H5T_CONV_INTERNAL_LLONG_LDOUBLE */
 
     /* From unsigned long long to floats */
     status |= H5T_register(H5T_PERS_HARD, "ullong_flt", native_ullong, native_float, H5T__conv_ullong_float, H5AC_ind_dxpl_id, FALSE);
     status |= H5T_register(H5T_PERS_HARD, "ullong_dbl", native_ullong, native_double, H5T__conv_ullong_double, H5AC_ind_dxpl_id, FALSE);
+#ifdef H5T_CONV_INTERNAL_ULLONG_LDOUBLE
     status |= H5T_register(H5T_PERS_HARD, "ullong_ldbl", native_ullong, native_ldouble, H5T__conv_ullong_ldouble, H5AC_ind_dxpl_id, FALSE);
+#endif /* H5T_CONV_INTERNAL_ULLONG_LDOUBLE */
 
     /* From floats to char */
     status |= H5T_register(H5T_PERS_HARD, "flt_schar", native_float, native_schar, H5T__conv_float_schar, H5AC_ind_dxpl_id, FALSE);
@@ -1271,12 +1275,16 @@ H5T_init_interface(void)
     /* From floats to long long */
     status |= H5T_register(H5T_PERS_HARD, "flt_llong", native_float, native_llong, H5T__conv_float_llong, H5AC_ind_dxpl_id, FALSE);
     status |= H5T_register(H5T_PERS_HARD, "dbl_llong", native_double, native_llong, H5T__conv_double_llong, H5AC_ind_dxpl_id, FALSE);
+#ifdef H5T_CONV_INTERNAL_LDOUBLE_LLONG
     status |= H5T_register(H5T_PERS_HARD, "ldbl_llong", native_ldouble, native_llong, H5T__conv_ldouble_llong, H5AC_ind_dxpl_id, FALSE);
+#endif /* H5T_CONV_INTERNAL_LDOUBLE_LLONG */
 
     /* From floats to unsigned long long */
     status |= H5T_register(H5T_PERS_HARD, "flt_ullong", native_float, native_ullong, H5T__conv_float_ullong, H5AC_ind_dxpl_id, FALSE);
     status |= H5T_register(H5T_PERS_HARD, "dbl_ullong", native_double, native_ullong, H5T__conv_double_ullong, H5AC_ind_dxpl_id, FALSE);
+#if H5T_CONV_INTERNAL_LDOUBLE_ULLONG
     status |= H5T_register(H5T_PERS_HARD, "ldbl_ullong", native_ldouble, native_ullong, H5T__conv_ldouble_ullong, H5AC_ind_dxpl_id, FALSE);
+#endif /* H5T_CONV_INTERNAL_LDOUBLE_ULLONG */
 
     /*
      * The special no-op conversion is the fastest, so we list it last. The
diff --git a/src/H5Tconv.c b/src/H5Tconv.c
index 81c947d..b14f6e5 100644
--- a/src/H5Tconv.c
+++ b/src/H5Tconv.c
@@ -7936,6 +7936,7 @@ H5T__conv_llong_double (hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata,
  *
  *-------------------------------------------------------------------------
  */
+#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,
@@ -7944,6 +7945,7 @@ H5T__conv_llong_ldouble (hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata,
 {
     H5T_CONV_xF(LLONG, LDOUBLE, long long, long double, -, -);
 }
+#endif /* H5T_CONV_INTERNAL_LLONG_LDOUBLE */
 
 
 /*-------------------------------------------------------------------------
@@ -8011,6 +8013,7 @@ H5T__conv_ullong_double (hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata,
  *
  *-------------------------------------------------------------------------
  */
+#if H5T_CONV_INTERNAL_ULLONG_LDOUBLE
 herr_t
 H5T__conv_ullong_ldouble (hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata,
 		       size_t nelmts, size_t buf_stride,
@@ -8019,6 +8022,7 @@ H5T__conv_ullong_ldouble (hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata,
 {
     H5T_CONV_xF(ULLONG, LDOUBLE, unsigned long long, long double, -, -);
 }
+#endif /*H5T_CONV_INTERNAL_ULLONG_LDOUBLE*/
 
 
 /*-------------------------------------------------------------------------
@@ -8792,6 +8796,7 @@ H5_GCC_DIAG_ON(float-equal)
  *
  *-------------------------------------------------------------------------
  */
+#if H5T_CONV_INTERNAL_LDOUBLE_LLONG
 herr_t
 H5T__conv_ldouble_llong (hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata,
 		       size_t nelmts, size_t buf_stride,
@@ -8802,6 +8807,7 @@ H5_GCC_DIAG_OFF(float-equal)
     H5T_CONV_Fx(LDOUBLE, LLONG, long double, long long, LLONG_MIN, LLONG_MAX);
 H5_GCC_DIAG_ON(float-equal)
 }
+#endif /*H5T_CONV_INTERNAL_LDOUBLE_LLONG*/
 
 
 /*-------------------------------------------------------------------------
@@ -8819,6 +8825,7 @@ H5_GCC_DIAG_ON(float-equal)
  *
  *-------------------------------------------------------------------------
  */
+#if H5T_CONV_INTERNAL_LDOUBLE_ULLONG
 herr_t
 H5T__conv_ldouble_ullong (hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata,
 		       size_t nelmts, size_t buf_stride,
@@ -8829,6 +8836,7 @@ H5_GCC_DIAG_OFF(float-equal)
     H5T_CONV_Fx(LDOUBLE, ULLONG, long double, unsigned long long, 0, ULLONG_MAX);
 H5_GCC_DIAG_ON(float-equal)
 }
+#endif /*H5T_CONV_INTERNAL_LDOUBLE_ULLONG*/
 
 
 /*-------------------------------------------------------------------------
diff --git a/src/H5Tpkg.h b/src/H5Tpkg.h
index 4697bfc..0b0cd61 100644
--- a/src/H5Tpkg.h
+++ b/src/H5Tpkg.h
@@ -111,6 +111,39 @@
                                                 /* (_not_ setting H5T_VISIT_SIMPLE and setting either H5T_VISIT_COMPLEX_FIRST or H5T_VISIT_COMPLEX_LAST will mean visiting all nodes _except_ "simple" "leafs" in the "tree" */
 
 
+/* Define an internal macro for converting long long to long double.  Mac OS 10.4 gives some
+ * incorrect conversions. */
+#if (H5_WANT_DATA_ACCURACY && defined(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 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.
+ * Mac OS 10.4 gives some incorrect result. */
+#if (H5_WANT_DATA_ACCURACY && defined(H5_LLONG_TO_LDOUBLE_CORRECT)) || (!H5_WANT_DATA_ACCURACY)
+#define H5T_CONV_INTERNAL_ULLONG_LDOUBLE         1
+#endif
+
+/* Define an internal macro for converting long double to long long.  SGI compilers give some incorrect
+ * 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 && defined(H5_LDOUBLE_TO_LLONG_ACCURATE)) || \
+    (!H5_WANT_DATA_ACCURACY)
+#define H5T_CONV_INTERNAL_LDOUBLE_LLONG         1
+#endif
+
+/* 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 && defined(H5_LDOUBLE_TO_LLONG_ACCURATE)) || \
+    (!H5_WANT_DATA_ACCURACY)
+#define H5T_CONV_INTERNAL_LDOUBLE_ULLONG         1
+#else
+#define H5T_CONV_INTERNAL_LDOUBLE_ULLONG         0
+#endif
+
 /* Statistics about a conversion function */
 struct H5T_stats_t {
     unsigned	ncalls;			/*num calls to conversion function   */
diff --git a/src/H5config.h.in b/src/H5config.h.in
index ac781fc..c0f4466 100644
--- a/src/H5config.h.in
+++ b/src/H5config.h.in
@@ -368,10 +368,18 @@
 /* Define if HDF5's high-level library headers should be included in hdf5.h */
 #undef INCLUDE_HL
 
+/* Define if your system can convert long double to (unsigned) long long
+   values correctly. */
+#undef LDOUBLE_TO_LLONG_ACCURATE
+
 /* Define if your system converts long double to (unsigned) long values with
    special algorithm. */
 #undef LDOUBLE_TO_LONG_SPECIAL
 
+/* Define if your system can convert (unsigned) long long to long double
+   values correctly. */
+#undef LLONG_TO_LDOUBLE_CORRECT
+
 /* Define if your system can convert (unsigned) long to long double values
    with special algorithm. */
 #undef LONG_TO_LDOUBLE_SPECIAL
@@ -554,6 +562,9 @@
 /* Version number of package */
 #undef VERSION
 
+/* Data accuracy is prefered to speed during data conversions */
+#undef WANT_DATA_ACCURACY
+
 /* Check exception handling functions during data conversions */
 #undef WANT_DCONV_EXCEPTION
 
diff --git a/test/dt_arith.c b/test/dt_arith.c
index 8ededc7..b3f5cad 100644
--- a/test/dt_arith.c
+++ b/test/dt_arith.c
@@ -5032,8 +5032,32 @@ run_int_fp_conv(const char *name)
 #endif
 #endif /* H5_SIZEOF_LONG!=H5_SIZEOF_INT */
 #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);
+#else /* H5_LLONG_TO_LDOUBLE_CORRECT */
+    {
+        char		str[256];		/*hello string		*/
+
+        HDsnprintf(str, sizeof(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_LLONG_TO_LDOUBLE_CORRECT
     nerrors += test_conv_int_fp(name, TEST_NORMAL, H5T_NATIVE_ULLONG, H5T_NATIVE_LDOUBLE);
+#else /* H5_LLONG_TO_LDOUBLE_CORRECT */
+    {
+        char		str[256];		/*hello string		*/
+
+        HDsnprintf(str, sizeof(str), "Testing %s %s -> %s conversions",
+                name, "unsigned long long", "long double");
+        printf("%-70s", str);
+        SKIPPED();
+        HDputs("    Test skipped due to compiler not handling conversion.");
+    }
+#endif /* H5_LLONG_TO_LDOUBLE_CORRECT */
 #endif
 #endif
 
@@ -5134,8 +5158,40 @@ run_fp_int_conv(const char *name)
 #endif /*H5_SIZEOF_LONG!=H5_SIZEOF_INT && H5_SIZEOF_LONG_DOUBLE!=0 */
 
 #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);
+#else /*H5_LDOUBLE_TO_LLONG_ACCURATE*/
+        {
+            char		str[256];		/*string		*/
+
+            HDsnprintf(str, sizeof(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 defined(H5_LDOUBLE_TO_LLONG_ACCURATE)
         nerrors += test_conv_int_fp(name, test_values, H5T_NATIVE_LDOUBLE, H5T_NATIVE_ULLONG);
+#else /*H5_LDOUBLE_TO_LLONG_ACCURATE*/
+        {
+            char		str[256];		/*string		*/
+
+            HDsnprintf(str, sizeof(str), "Testing %s %s -> %s conversions",
+                    name, "long double", "unsigned 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*/
 #endif
 #endif
 #ifndef H5_VMS
-- 
cgit v0.12