From db223e85b2ae5113c1579a7d0f437d0226a416f5 Mon Sep 17 00:00:00 2001 From: Raymond Lu Date: Wed, 25 May 2005 10:59:30 -0500 Subject: [svn-r10797] Purpose: A feature Description: Cygwin compiler doesn't do rounding correctly when converting "unsigned long long" to "long double". Solution: Added test case to variable detection of "hdf5_cv_ullong_to_ldouble_precision_works". Platforms tested: sleipnir, fuss, and shanti - mainly to test configuration, don't need to run h5committest. --- configure | 46 ++++++++++++++++++++++++++++++++++++++++------ configure.in | 52 +++++++++++++++++++++++++++++++++++++++++++--------- 2 files changed, 83 insertions(+), 15 deletions(-) diff --git a/configure b/configure index 33684ce..4bd8fec 100755 --- a/configure +++ b/configure @@ -50273,13 +50273,23 @@ cat >>conftest.$ac_ext <<_ACEOF int main(void) { + /* General variables */ + int endian; + int tst_value = 1; + int ret = 0; + + /* For FreeBSD */ unsigned long long l = 0xa601e80bda85fcefULL; long double ld; unsigned char *c1, *c2; size_t size; - int endian; - int tst_value = 1; - int ret = 0; + + /* For Cygwin */ + unsigned long long l_cyg = 0xfffffffffffffff0ULL; + long double ld_cyg; + unsigned char *c2_cyg; + size_t size_cyg; + /* Determine this system's endianess */ c1 = (unsigned char*)calloc(1, sizeof(int)); @@ -50289,6 +50299,7 @@ cat >>conftest.$ac_ext <<_ACEOF else endian = 1; /* big endian */ + /* For FreeBSD */ size = sizeof(long double); memset(&ld, 0, size); ld = (long double)l; @@ -50299,12 +50310,35 @@ cat >>conftest.$ac_ext <<_ACEOF /* Test if the last 2 bytes of mantissa are lost. Mainly for FreeBSD on Intel * architecture(sleipnir) where it happens. */ /*if(endian==0 && c2[0]==0 && c2[1]==0)*/ /*little endian*/ - if(endian==0 && c2[0]==0) /*little endian*/ + if(endian==0 && c2[0]==0) { /*little endian*/ + ret = 1; + goto done; + } + + /* For Cygwin */ + size_cyg = sizeof(long double); + memset(&ld_cyg, 0, size); + ld_cyg = (long double)l_cyg; + + c2_cyg = (unsigned char*)calloc(1, size_cyg); + memcpy((void*)c2_cyg, &ld_cyg, size_cyg); + + /* Test if the last 4 bytes(roughly) of mantissa are rounded up. Mainly for Cygwin + * where the values like 0xffffffffffffffff, 0xfffffffffffffffe, ..., + * 0xfffffffffffff000 ... are rounded up as 0x0000403f8000000000000000 + * instead of 0x0000403effffffffffffffff, 0x0000403efffffffffffffffe, ..., + * 0x0000403efffffffffffff000 ... + */ + if(endian==0 && c2_cyg[0]==0 && c2_cyg[1]==0 && c2_cyg[2]==0 && c2_cyg[3]==0) ret = 1; - free(c1); - free(c2); done: + if(c1) + free(c1); + if(c2) + free(c2); + if(c2_cyg) + free(c2_cyg); exit(ret); } diff --git a/configure.in b/configure.in index 292e484..6bc90e9 100644 --- a/configure.in +++ b/configure.in @@ -2646,21 +2646,31 @@ dnl Set the flag to indicate that the machine can convert from dnl 'unsigned long long' to 'long double' without precision loss. dnl (This flag should be set for all machines, except for FreeBSD(sleipnir) dnl where the last 2 bytes of mantissa are lost when compiler tries to do -dnl the conversion.) +dnl the conversion, and Cygwin where compiler doesn't do rounding correctly.) dnl AC_MSG_CHECKING([if converting unsigned long long to long double with precision work]) AC_CACHE_VAL([hdf5_cv_ullong_to_ldouble_precision_works], [AC_TRY_RUN([ int main(void) { + /* General variables */ + int endian; + int tst_value = 1; + int ret = 0; + + /* For FreeBSD */ unsigned long long l = 0xa601e80bda85fcefULL; long double ld; unsigned char *c1, *c2; size_t size; - int endian; - int tst_value = 1; - int ret = 0; + /* For Cygwin */ + unsigned long long l_cyg = 0xfffffffffffffff0ULL; + long double ld_cyg; + unsigned char *c2_cyg; + size_t size_cyg; + + /* Determine this system's endianess */ c1 = (unsigned char*)calloc(1, sizeof(int)); memcpy((void*)c1, &tst_value, sizeof(int)); @@ -2668,7 +2678,8 @@ AC_CACHE_VAL([hdf5_cv_ullong_to_ldouble_precision_works], endian = 0; /* little endian */ else endian = 1; /* big endian */ - + + /* For FreeBSD */ size = sizeof(long double); memset(&ld, 0, size); ld = (long double)l; @@ -2679,12 +2690,35 @@ AC_CACHE_VAL([hdf5_cv_ullong_to_ldouble_precision_works], /* Test if the last 2 bytes of mantissa are lost. Mainly for FreeBSD on Intel * architecture(sleipnir) where it happens. */ /*if(endian==0 && c2[0]==0 && c2[1]==0)*/ /*little endian*/ - if(endian==0 && c2[0]==0) /*little endian*/ + if(endian==0 && c2[0]==0) { /*little endian*/ ret = 1; - - free(c1); - free(c2); + goto done; + } + + /* For Cygwin */ + size_cyg = sizeof(long double); + memset(&ld_cyg, 0, size); + ld_cyg = (long double)l_cyg; + + c2_cyg = (unsigned char*)calloc(1, size_cyg); + memcpy((void*)c2_cyg, &ld_cyg, size_cyg); + + /* Test if the last 4 bytes(roughly) of mantissa are rounded up. Mainly for Cygwin + * where the values like 0xffffffffffffffff, 0xfffffffffffffffe, ..., + * 0xfffffffffffff000 ... are rounded up as 0x0000403f8000000000000000 + * instead of 0x0000403effffffffffffffff, 0x0000403efffffffffffffffe, ..., + * 0x0000403efffffffffffff000 ... + */ + if(endian==0 && c2_cyg[0]==0 && c2_cyg[1]==0 && c2_cyg[2]==0 && c2_cyg[3]==0) + ret = 1; + done: + if(c1) + free(c1); + if(c2) + free(c2); + if(c2_cyg) + free(c2_cyg); exit(ret); } ], [hdf5_cv_ullong_to_ldouble_precision_works=yes], [hdf5_cv_ullong_to_ldouble_precision_works=no],)]) -- cgit v0.12