diff options
author | Raymond Lu <songyulu@hdfgroup.org> | 2010-10-28 16:34:31 (GMT) |
---|---|---|
committer | Raymond Lu <songyulu@hdfgroup.org> | 2010-10-28 16:34:31 (GMT) |
commit | e05528194deb238fa71820c45c425b5953b1b938 (patch) | |
tree | a5948c65388e464a12a7024a515362f76b4ce0cd /configure.in | |
parent | 71bf205c79d20738bf8f5a19907a80e428369d50 (diff) | |
download | hdf5-e05528194deb238fa71820c45c425b5953b1b938.zip hdf5-e05528194deb238fa71820c45c425b5953b1b938.tar.gz hdf5-e05528194deb238fa71820c45c425b5953b1b938.tar.bz2 |
[svn-r19693] Bug 2008 - IBM Power6 Linux uses special conversion algorithms to convert some values from long
double to (unsigned) long and from (unsigned) long to long double. I added tests in configure.in
to detect these algorithms. Before I can figure out them, I disable the tests in dt_arith.c.
Tested on jam, heiwa, amani, IBM Power6 Linux machine in Holland (huygens.sara.nl).
Diffstat (limited to 'configure.in')
-rw-r--r-- | configure.in | 162 |
1 files changed, 162 insertions, 0 deletions
diff --git a/configure.in b/configure.in index d66b805..e681580 100644 --- a/configure.in +++ b/configure.in @@ -3587,6 +3587,167 @@ else fi dnl ---------------------------------------------------------------------- +dnl Set the flag to indicate that the machine is using a special algorithm to convert +dnl 'long double' to '(unsigned) long' values. (This flag should only be set for +dnl the IBM Power6 Linux. When the bit sequence of long double is +dnl 0x4351ccf385ebc8a0bfcc2a3c3d855620, the converted value of (unsigned)long +dnl is 0x004733ce17af227f, not the same as the library's conversion to 0x004733ce17af2282. +dnl The machine's conversion gets the correct value. We define the macro and disable +dnl this kind of test until we figure out what algorithm they use. +dnl +AC_MSG_CHECKING([if using special algorithm to convert long double to (unsigned) long values]) + +if test ${ac_cv_sizeof_long_double} = 0; then + hdf5_cv_ldouble_to_long_special=${hdf5_cv_ldouble_to_long_special=no} +else + AC_CACHE_VAL([hdf5_cv_ldouble_to_long_special], + [AC_TRY_RUN([ + int main(void) + { + long double ld = 20041683600089727.779961L; + long ll; + unsigned long ull; + unsigned char s[16]; + unsigned char s2[8]; + int ret = 1; + + if(sizeof(long double) == 16 && sizeof(long) == 8) { + /*make sure the long double type 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) { + + /* Assign the hexadecimal value of long double type. */ + 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; + s[12]=0x3d; s[13]=0x85; s[14]=0x56; s[15]=0x20; + + memcpy(&ld, s, 16); + + ll = (long)ld; + memcpy(s2, &ll, 8); + + /* The library's algorithm converts it to 0x 00 47 33 ce 17 af 22 82 + * and gets wrong value 20041683600089730 on the IBM Power6 Linux. + * But the IBM Power6 Linux converts it to 0x00 47 33 ce 17 af 22 7f + * and gets the correct value 20041683600089727. It uses some special + * algorithm. We're going to define the macro and skip the test until + * we can figure out how they do it. */ + if(s2[0]==0x00 && s2[1]==0x47 && s2[2]==0x33 && s2[3]==0xce && + s2[4]==0x17 && s2[5]==0xaf && s2[6]==0x22 && s2[7]==0x7f) + ret = 0; + + ull = (unsigned long)ld; + memcpy(s2, &ull, 8); + + /* The unsigned long is the same as signed long. */ + if(s2[0]==0x00 && s2[1]==0x47 && s2[2]==0x33 && s2[3]==0xce && + s2[4]==0x17 && s2[5]==0xaf && s2[6]==0x22 && s2[7]==0x7f) + ret = 0; + } + } + + done: + exit(ret); + } + ], [hdf5_cv_ldouble_to_long_special=yes], [hdf5_cv_ldouble_to_long_special=no],)]) +fi + +if test ${hdf5_cv_ldouble_to_long_special} = "yes"; then + AC_DEFINE([LDOUBLE_TO_LONG_SPECIAL], [1], + [Define if your system converts long double to (unsigned) long values with special algorithm.]) + AC_MSG_RESULT([yes]) +else + AC_MSG_RESULT([no]) +fi + +dnl ---------------------------------------------------------------------- +dnl Set the flag to indicate that the machine is using a special algorithm +dnl to convert some values of '(unsigned) long' to 'long double' values. +dnl (This flag should be off for all machines, except for IBM Power6 Linux, +dnl when the bit sequences are 003fff..., 007fff..., 00ffff..., 01ffff..., +dnl ..., 7fffff..., the compiler uses a unknown algorithm. We define a +dnl macro and skip the test for now until we know about the algorithm. +dnl +AC_MSG_CHECKING([if using special algorithm to convert (unsigned) long to long double values]) + +if test ${ac_cv_sizeof_long_double} = 0; then + hdf5_cv_long_to_ldouble_special=${hdf5_cv_long_to_ldouble_special=no} +else + AC_CACHE_VAL([hdf5_cv_long_to_ldouble_special], + [AC_TRY_RUN([ + int main(void) + { + long double ld; + long ll; + unsigned long ull; + unsigned char s[16]; + int flag=0, ret=1; + + /*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)==8) { + ll = 0x003fffffffffffffL; + ld = (long double)ll; + memcpy(s, &ld, 16); + /* The library converts the value to 0x434fffffffffffff8000000000000000. + * In decimal it is 18014398509481982.000000, one value short of the original. + * The IBM Power6 Linux converts it to 0x4350000000000000bff0000000000000. + * The value is correct in decimal. It uses some special + * algorithm. We're going to define the macro and skip the test until + * we can figure out how they do it. */ + if(s[0]==0x43 && s[1]==0x50 && s[2]==0x00 && s[3]==0x00 && + s[4]==0x00 && s[5]==0x00 && s[6]==0x00 && s[7]==0x00 && + s[8]==0xbf && s[9]==0xf0 && s[10]==0x00 && s[11]==0x00 && + s[12]==0x00 && s[13]==0x00 && s[14]==0x00 && s[15]==0x00) + ret = 0; + } + if(flag==1 && sizeof(unsigned long)==8) { + ull = 0xffffffffffffffffUL; + ld = (long double)ull; + memcpy(s, &ld, 16); + /* Use a different value from signed long to test. The problem is the same + * for both long and unsigned long. The value is 18446744073709551615. + * The library converts the value to 0x43effffffffffffffe000000000000000. + * In decimal it's 18446744073709548544.000000, very different from the original. + * The IBM Power6 Linux converts it to 0x43f0000000000000bff0000000000000. + * The value is correct in decimal. It uses some special + * algorithm. We're going to define the macro and skip the test until + * we can figure out how they do it. */ + if(s[0]==0x43 && s[1]==0xf0 && s[2]==0x00 && s[3]==0x00 && + s[4]==0x00 && s[5]==0x00 && s[6]==0x00 && s[7]==0x00 && + s[8]==0xbf && s[9]==0xf0 && s[10]==0x00 && s[11]==0x00 && + s[12]==0x00 && s[13]==0x00 && s[14]==0x00 && s[15]==0x00) + ret = 0; + } + done: + exit(ret); + } + ], [hdf5_cv_long_to_ldouble_special=yes], [hdf5_cv_long_to_ldouble_special=no],)]) +fi + +if test ${hdf5_cv_long_to_ldouble_special} = "yes"; then + AC_DEFINE([LONG_TO_LDOUBLE_SPECIAL], [1], + [Define if your system can convert (unsigned) long to long double values with special algorithm.]) + AC_MSG_RESULT([yes]) +else + AC_MSG_RESULT([no]) +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 @@ -3649,6 +3810,7 @@ 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 |