diff options
author | Quincey Koziol <koziol@hdfgroup.org> | 2003-11-24 16:47:18 (GMT) |
---|---|---|
committer | Quincey Koziol <koziol@hdfgroup.org> | 2003-11-24 16:47:18 (GMT) |
commit | 6d8dd9c50412803fd3cc3af18c4e618c3b97cec3 (patch) | |
tree | e23e841019af738a69c2bf5633bd3a671dd4e3fb | |
parent | 2106568c9cf25cc350e688276268465366a50d8f (diff) | |
download | hdf5-6d8dd9c50412803fd3cc3af18c4e618c3b97cec3.zip hdf5-6d8dd9c50412803fd3cc3af18c4e618c3b97cec3.tar.gz hdf5-6d8dd9c50412803fd3cc3af18c4e618c3b97cec3.tar.bz2 |
[svn-r7875] Purpose:
Omnibus floating-point bug fix changes
Description:
There are a number of problems in the floating-point conversion code that
were exposed by Ray's recent int<->float checkin:
- The 'my_isnan' code in test/dtypes.c was broken and would always return
true. The meant that the actual values in the float<->float conversion
tests were _never_ checked, hiding the other bugs included in this
checkin.
- A recent change I made to the type conversion code used "FLT_MIN" instead
of "-FLT_MAX" for the most negative 'float' value for the double->float
conversion, which meant that any the negative number that was converted
from a double to a float would have been mapped to zero, essentially.
- A change that Robb appeared to have made ~2.5 years ago to the "generic"
float->float conversion routine appears to be incorrect and I've backed
it out.
- Floating-point conversions on SGI's which converted denormalized values
would be mapped to zero instead of being propertly preserved in the new
type. This was addressed by an SGI-specific system call to prevent the
behavior.
Solution:
Described above, generally.
Platforms tested:
FreeBSD 4.9 (sleipnir)
h5committest
Misc. update:
release_docs/RELEASE update forthcoming...
-rwxr-xr-x | configure | 192 | ||||
-rw-r--r-- | configure.in | 8 | ||||
-rw-r--r-- | src/H5T.c | 178 | ||||
-rw-r--r-- | src/H5Tconv.c | 21 | ||||
-rw-r--r-- | src/H5Tpkg.h | 7 | ||||
-rw-r--r-- | src/H5config.h.in | 6 | ||||
-rw-r--r-- | test/dtypes.c | 130 |
7 files changed, 456 insertions, 86 deletions
@@ -9727,6 +9727,198 @@ fi done ;; + mips*-sgi*-irix*) + +for ac_header in sys/fpu.h +do +as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh` +if eval "test \"\${$as_ac_Header+set}\" = set"; then + echo "$as_me:$LINENO: checking for $ac_header" >&5 +echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6 +if eval "test \"\${$as_ac_Header+set}\" = set"; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +fi +echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_Header'}'`" >&5 +echo "${ECHO_T}`eval echo '${'$as_ac_Header'}'`" >&6 +else + # Is the header compilable? +echo "$as_me:$LINENO: checking $ac_header usability" >&5 +echo $ECHO_N "checking $ac_header usability... $ECHO_C" >&6 +cat >conftest.$ac_ext <<_ACEOF +#line $LINENO "configure" +#include "confdefs.h" +$ac_includes_default +#include <$ac_header> +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -s conftest.$ac_objext' + { (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 + ac_header_compiler=yes +else + echo "$as_me: failed program was:" >&5 +cat conftest.$ac_ext >&5 +ac_header_compiler=no +fi +rm -f conftest.$ac_objext conftest.$ac_ext +echo "$as_me:$LINENO: result: $ac_header_compiler" >&5 +echo "${ECHO_T}$ac_header_compiler" >&6 + +# Is the header present? +echo "$as_me:$LINENO: checking $ac_header presence" >&5 +echo $ECHO_N "checking $ac_header presence... $ECHO_C" >&6 +cat >conftest.$ac_ext <<_ACEOF +#line $LINENO "configure" +#include "confdefs.h" +#include <$ac_header> +_ACEOF +if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5 + (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1 + ac_status=$? + egrep -v '^ *\+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } >/dev/null; then + if test -s conftest.err; then + ac_cpp_err=$ac_c_preproc_warn_flag + else + ac_cpp_err= + fi +else + ac_cpp_err=yes +fi +if test -z "$ac_cpp_err"; then + ac_header_preproc=yes +else + echo "$as_me: failed program was:" >&5 + cat conftest.$ac_ext >&5 + ac_header_preproc=no +fi +rm -f conftest.err conftest.$ac_ext +echo "$as_me:$LINENO: result: $ac_header_preproc" >&5 +echo "${ECHO_T}$ac_header_preproc" >&6 + +# So? What about this header? +case $ac_header_compiler:$ac_header_preproc in + yes:no ) + { echo "$as_me:$LINENO: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&5 +echo "$as_me: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the preprocessor's result" >&5 +echo "$as_me: WARNING: $ac_header: proceeding with the preprocessor's result" >&2;};; + no:yes ) + { echo "$as_me:$LINENO: WARNING: $ac_header: present but cannot be compiled" >&5 +echo "$as_me: WARNING: $ac_header: present but cannot be compiled" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: check for missing prerequisite headers?" >&5 +echo "$as_me: WARNING: $ac_header: check for missing prerequisite headers?" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the preprocessor's result" >&5 +echo "$as_me: WARNING: $ac_header: proceeding with the preprocessor's result" >&2;};; +esac +echo "$as_me:$LINENO: checking for $ac_header" >&5 +echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6 +if eval "test \"\${$as_ac_Header+set}\" = set"; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + eval "$as_ac_Header=$ac_header_preproc" +fi +echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_Header'}'`" >&5 +echo "${ECHO_T}`eval echo '${'$as_ac_Header'}'`" >&6 + +fi +if test `eval echo '${'$as_ac_Header'}'` = yes; then + cat >>confdefs.h <<_ACEOF +#define `echo "HAVE_$ac_header" | $as_tr_cpp` 1 +_ACEOF + +fi + +done + + +for ac_func in get_fpc_csr +do +as_ac_var=`echo "ac_cv_func_$ac_func" | $as_tr_sh` +echo "$as_me:$LINENO: checking for $ac_func" >&5 +echo $ECHO_N "checking for $ac_func... $ECHO_C" >&6 +if eval "test \"\${$as_ac_var+set}\" = set"; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +#line $LINENO "configure" +#include "confdefs.h" +/* System header to define __stub macros and hopefully few prototypes, + which can conflict with char $ac_func (); below. */ +#include <assert.h> +/* Override any gcc2 internal prototype to avoid an error. */ +#ifdef __cplusplus +extern "C" +#endif +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char $ac_func (); +char (*f) (); + +#ifdef F77_DUMMY_MAIN +# ifdef __cplusplus + extern "C" +# endif + int F77_DUMMY_MAIN() { return 1; } +#endif +int +main () +{ +/* The GNU C library defines this for functions which it implements + to always fail with ENOSYS. Some functions are actually named + something starting with __ and the normal name is an alias. */ +#if defined (__stub_$ac_func) || defined (__stub___$ac_func) +choke me +#else +f = $ac_func; +#endif + + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext 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='test -s 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 + eval "$as_ac_var=yes" +else + echo "$as_me: failed program was:" >&5 +cat conftest.$ac_ext >&5 +eval "$as_ac_var=no" +fi +rm -f conftest.$ac_objext conftest$ac_exeext conftest.$ac_ext +fi +echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_var'}'`" >&5 +echo "${ECHO_T}`eval echo '${'$as_ac_var'}'`" >&6 +if test `eval echo '${'$as_ac_var'}'` = yes; then + cat >>confdefs.h <<_ACEOF +#define `echo "HAVE_$ac_func" | $as_tr_cpp` 1 +_ACEOF + +fi +done + + ;; esac case "$host_cpu-$host_vendor-$host_os" in diff --git a/configure.in b/configure.in index 0ef9848..b53ca00 100644 --- a/configure.in +++ b/configure.in @@ -692,6 +692,14 @@ case "$host" in dnl many problems with including them. AC_CHECK_HEADERS([sys/sysinfo.h sys/proc.h]) ;; + mips*-sgi*-irix*) + dnl The <sys/fpu.h> is needed on the SGI machines to turn off + dnl denormalized floating-point values going to zero. We do *not* + dnl attempt to dnl locate these files on other systems because there + dnl may be problems with including them. + AC_CHECK_HEADERS([sys/fpu.h]) + AC_CHECK_FUNCS([get_fpc_csr]) + ;; esac dnl ---------------------------------------------------------------------- @@ -35,6 +35,11 @@ #include "H5Pprivate.h" /* Property Lists */ #include "H5Tpkg.h" /*data-type functions */ +/* Check for header needed for SGI floating-point code */ +#ifdef H5_HAVE_SYS_FPU_H +#include <sys/fpu.h> +#endif /* H5_HAVE_SYS_FPU_H */ + /* Interface initialization */ static int interface_initialize_g = 0; #define INTERFACE_INIT H5T_init_interface @@ -215,6 +220,13 @@ size_t H5T_NATIVE_UINT_LEAST64_ALIGN_g = 0; size_t H5T_NATIVE_INT_FAST64_ALIGN_g = 0; size_t H5T_NATIVE_UINT_FAST64_ALIGN_g = 0; +/* Useful floating-point values for conversion routines */ +/* (+/- Inf for all floating-point types) */ +float H5T_NATIVE_FLOAT_POS_INF_g = 0.0; +float H5T_NATIVE_FLOAT_NEG_INF_g = 0.0; +double H5T_NATIVE_DOUBLE_POS_INF_g = 0.0; +double H5T_NATIVE_DOUBLE_NEG_INF_g = 0.0; + /* * The path database. Each path has a source and destination data type pair @@ -467,6 +479,165 @@ done: } +/*------------------------------------------------------------------------- + * Function: H5T_init_inf + * + * Purpose: Initialize the +/- Infinity floating-poing values for type + * conversion. + * + * Return: Success: non-negative + * + * Failure: negative + * + * Programmer: Quincey Koziol + * Saturday, November 22, 2003 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +static herr_t +H5T_init_inf(void) +{ + H5T_t *dst_p; /* Datatype type operate on */ + H5T_atomic_t *dst; /* Datatype's atomic info */ + uint8_t *d; /* Pointer to value to set */ + size_t half_size; /* Half the type size */ + size_t u; /* Local index value */ + herr_t ret_value=SUCCEED; /* Return value */ + + FUNC_ENTER_NOINIT(H5T_init_inf); + + /* Get the float datatype */ + if (NULL==(dst_p=H5I_object(H5T_NATIVE_FLOAT_g))) + HGOTO_ERROR (H5E_ARGS, H5E_BADTYPE, FAIL, "not a datatype"); + dst = &dst_p->u.atomic; + + /* Check that we can re-order the bytes correctly */ + if (H5T_ORDER_LE!=dst->order && H5T_ORDER_BE!=dst->order) + HGOTO_ERROR (H5E_DATATYPE, H5E_UNSUPPORTED, FAIL, "unsupported byte order"); + + /* +Inf */ + d=(uint8_t *)&H5T_NATIVE_FLOAT_POS_INF_g; + H5T_bit_set (d, dst->u.f.sign, 1, FALSE); + H5T_bit_set (d, dst->u.f.epos, dst->u.f.esize, TRUE); + H5T_bit_set (d, dst->u.f.mpos, dst->u.f.msize, FALSE); + + /* Swap the bytes if the machine architecture is big-endian */ + if (H5T_ORDER_BE==dst->order) { + half_size = dst_p->size/2; + for (u=0; u<half_size; u++) { + uint8_t tmp = d[dst_p->size-(u+1)]; + d[dst_p->size-(u+1)] = d[u]; + d[u] = tmp; + } + } + + /* -Inf */ + d=(uint8_t *)&H5T_NATIVE_FLOAT_NEG_INF_g; + H5T_bit_set (d, dst->u.f.sign, 1, TRUE); + H5T_bit_set (d, dst->u.f.epos, dst->u.f.esize, TRUE); + H5T_bit_set (d, dst->u.f.mpos, dst->u.f.msize, FALSE); + + /* Swap the bytes if the machine architecture is big-endian */ + if (H5T_ORDER_BE==dst->order) { + half_size = dst_p->size/2; + for (u=0; u<half_size; u++) { + uint8_t tmp = d[dst_p->size-(u+1)]; + d[dst_p->size-(u+1)] = d[u]; + d[u] = tmp; + } + } + + /* Get the double datatype */ + if (NULL==(dst_p=H5I_object(H5T_NATIVE_DOUBLE_g))) + HGOTO_ERROR (H5E_ARGS, H5E_BADTYPE, FAIL, "not a datatype"); + dst = &dst_p->u.atomic; + + /* Check that we can re-order the bytes correctly */ + if (H5T_ORDER_LE!=dst->order && H5T_ORDER_BE!=dst->order) + HGOTO_ERROR (H5E_DATATYPE, H5E_UNSUPPORTED, FAIL, "unsupported byte order"); + + /* +Inf */ + d=(uint8_t *)&H5T_NATIVE_DOUBLE_POS_INF_g; + H5T_bit_set (d, dst->u.f.sign, 1, FALSE); + H5T_bit_set (d, dst->u.f.epos, dst->u.f.esize, TRUE); + H5T_bit_set (d, dst->u.f.mpos, dst->u.f.msize, FALSE); + + /* Swap the bytes if the machine architecture is big-endian */ + if (H5T_ORDER_BE==dst->order) { + half_size = dst_p->size/2; + for (u=0; u<half_size; u++) { + uint8_t tmp = d[dst_p->size-(u+1)]; + d[dst_p->size-(u+1)] = d[u]; + d[u] = tmp; + } + } + + /* -Inf */ + d=(uint8_t *)&H5T_NATIVE_DOUBLE_NEG_INF_g; + H5T_bit_set (d, dst->u.f.sign, 1, TRUE); + H5T_bit_set (d, dst->u.f.epos, dst->u.f.esize, TRUE); + H5T_bit_set (d, dst->u.f.mpos, dst->u.f.msize, FALSE); + + /* Swap the bytes if the machine architecture is big-endian */ + if (H5T_ORDER_BE==dst->order) { + half_size = dst_p->size/2; + for (u=0; u<half_size; u++) { + uint8_t tmp = d[dst_p->size-(u+1)]; + d[dst_p->size-(u+1)] = d[u]; + d[u] = tmp; + } + } + +done: + FUNC_LEAVE_NOAPI(ret_value); +} + + +/*------------------------------------------------------------------------- + * Function: H5T_init_hw + * + * Purpose: Perform hardware specific [floating-point] initialization + * + * Return: Success: non-negative + * + * Failure: negative + * + * Programmer: Quincey Koziol + * Monday, November 24, 2003 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +static herr_t +H5T_init_hw(void) +{ +#ifdef H5_HAVE_GET_FPC_CSR + union fpc_csr csr; /* Union to hold results of floating-point status register query */ +#endif /* H5_HAVE_GET_FPC_CSR */ + herr_t ret_value=SUCCEED; /* Return value */ + + FUNC_ENTER_NOINIT(H5T_init_hw); + +#ifdef H5_HAVE_GET_FPC_CSR + /* [This code is specific to SGI machines] */ + + /* Get the floating-point status register */ + csr.fc_word=get_fpc_csr(); + + /* If the "flush denormalized values to zero" flag is set, unset it */ + if(csr.fc_struct.flush) { + csr.fc_struct.flush=0; + set_fpc_csr(csr.fc_word); + } /* end if */ +#endif /* H5_HAVE_GET_FPC_CSR */ + + FUNC_LEAVE_NOAPI(ret_value); +} + + /*-------------------------------------------------------------------------- NAME H5T_init_interface -- Initialize interface-specific information @@ -529,6 +700,10 @@ H5T_init_interface(void) /* Only 16 (numbered 0-15) are supported in the current file format */ assert(H5T_NCLASSES<16); + /* Perform any necessary hardware initializations */ + if(H5T_init_hw()<0) + HGOTO_ERROR (H5E_DATATYPE, H5E_CANTINIT, FAIL, "unable to initialize interface"); + /* * Initialize pre-defined native data types from code generated during * the library configuration by H5detect. @@ -993,6 +1168,9 @@ H5T_init_interface(void) */ status |= H5T_register(H5T_PERS_HARD, "no-op", native_int, native_int, H5T_conv_noop, H5AC_dxpl_id); + /* Initialize the +/- Infinity values for floating-point types */ + status |= H5T_init_inf(); + if (status<0) HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL, "unable to register conversion function(s)"); diff --git a/src/H5Tconv.c b/src/H5Tconv.c index 8e40b0a..53f0b29 100644 --- a/src/H5Tconv.c +++ b/src/H5Tconv.c @@ -307,9 +307,23 @@ H5FL_BLK_DEFINE_STATIC(array_seq); H5T_CONV(H5T_CONV_xX, double, STYPE, DTYPE, ST, DT, D_MIN, D_MAX) \ } +/* Same as H5T_CONV_Xx_CORE, except that instead of using D_MAX and D_MIN + * when an overflow occurs, use the 'float' infinity values. + */ +#define H5T_CONV_Ff_CORE(S,D,STYPE,DTYPE,ST,DT,D_MIN,D_MAX) { \ + if (*((ST*)S) > (DT)(D_MAX)) { \ + if (!H5T_overflow_g || (H5T_overflow_g)(src_id, dst_id, S, D)<0) \ + *((DT*)D) = (H5T_NATIVE_FLOAT_POS_INF_g); \ + } else if (*((ST*)S) < (D_MIN)) { \ + if (!H5T_overflow_g || (H5T_overflow_g)(src_id, dst_id, S, D)<0) \ + *((DT*)D) = (H5T_NATIVE_FLOAT_NEG_INF_g); \ + } else \ + *((DT*)D) = (DT)(*((ST*)S)); \ +} + #define H5T_CONV_Ff(STYPE,DTYPE,ST,DT,D_MIN,D_MAX) { \ assert(sizeof(ST)>=sizeof(DT)); \ - H5T_CONV(H5T_CONV_Xx, double, STYPE, DTYPE, ST, DT, D_MIN, D_MAX) \ + H5T_CONV(H5T_CONV_Ff, double, STYPE, DTYPE, ST, DT, D_MIN, D_MAX) \ } #define H5T_CONV_xF(STYPE,DTYPE,ST,DT,D_MIN,D_MAX) { \ @@ -3351,6 +3365,8 @@ H5T_conv_f_f (hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata, hsize_t nelmts, } /* Write the exponent */ +#ifdef OLD_WAY +/* It appears to be incorrect to increment the exponent when the carry is set -QAK */ if (carry) { expo++; if (expo>=expo_max) { @@ -3379,6 +3395,7 @@ H5T_conv_f_f (hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata, hsize_t nelmts, H5T_bit_set(d, dst.u.f.mpos, dst.u.f.msize, FALSE); } } +#endif /* OLD_WAY */ H5_CHECK_OVERFLOW(expo,hssize_t,hsize_t); H5T_bit_set_d(d, dst.u.f.epos, dst.u.f.esize, (hsize_t)expo); @@ -6674,7 +6691,7 @@ H5T_conv_double_float (hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata, FUNC_ENTER_NOAPI(H5T_conv_float_double, FAIL); - H5T_CONV_Ff(DOUBLE, FLOAT, double, float, FLT_MIN, FLT_MAX); + H5T_CONV_Ff(DOUBLE, FLOAT, double, float, -FLT_MAX, FLT_MAX); done: FUNC_LEAVE_NOAPI(ret_value); diff --git a/src/H5Tpkg.h b/src/H5Tpkg.h index 9058d90..d87cc2f 100644 --- a/src/H5Tpkg.h +++ b/src/H5Tpkg.h @@ -305,6 +305,13 @@ H5_DLLVAR size_t H5T_NATIVE_UINT_LEAST64_ALIGN_g; H5_DLLVAR size_t H5T_NATIVE_INT_FAST64_ALIGN_g; H5_DLLVAR size_t H5T_NATIVE_UINT_FAST64_ALIGN_g; +/* Useful floating-point values for conversion routines */ +/* (+/- Inf for all floating-point types) */ +H5_DLLVAR float H5T_NATIVE_FLOAT_POS_INF_g; +H5_DLLVAR float H5T_NATIVE_FLOAT_NEG_INF_g; +H5_DLLVAR double H5T_NATIVE_DOUBLE_POS_INF_g; +H5_DLLVAR double H5T_NATIVE_DOUBLE_NEG_INF_g; + /* Common functions */ H5_DLL herr_t H5T_init_interface(void); H5_DLL H5T_t *H5T_create(H5T_class_t type, size_t size); diff --git a/src/H5config.h.in b/src/H5config.h.in index 20ea728..f2348c4 100644 --- a/src/H5config.h.in +++ b/src/H5config.h.in @@ -69,6 +69,9 @@ /* Define to 1 if you have the `gettimeofday' function. */ #undef HAVE_GETTIMEOFDAY +/* Define to 1 if you have the `get_fpc_csr' function. */ +#undef HAVE_GET_FPC_CSR + /* Define to 1 if you have the <globus_common.h> header file. */ #undef HAVE_GLOBUS_COMMON_H @@ -272,6 +275,9 @@ /* Define to 1 if you have the <sys/filio.h> header file. */ #undef HAVE_SYS_FILIO_H +/* Define to 1 if you have the <sys/fpu.h> header file. */ +#undef HAVE_SYS_FPU_H + /* Define to 1 if you have the <sys/ioctl.h> header file. */ #undef HAVE_SYS_IOCTL_H diff --git a/test/dtypes.c b/test/dtypes.c index 3dc06ba..448115c 100644 --- a/test/dtypes.c +++ b/test/dtypes.c @@ -107,8 +107,9 @@ static int num_opaque_conversions_g = 0; #define aligned_free(M) free((char*)(M)-ALIGNMENT) void some_dummy_func(float x); -hbool_t overflows(unsigned char *origin_bits, dtype_t src_dtype, +static hbool_t overflows(unsigned char *origin_bits, dtype_t src_dtype, size_t src_size_bytes, size_t dst_num_bits); +static int my_isnan(dtype_t type, void *val); /*------------------------------------------------------------------------- @@ -2971,10 +2972,7 @@ test_conv_int_1(const char *name, hid_t src, hid_t dst) sizeof(unsigned long_long)); hw_char = (char)(*((unsigned long_long*)aligned)); break; - case FLT_FLOAT: - case FLT_DOUBLE: - case FLT_LDOUBLE: - case OTHER: + default: break; } } else if (INT_UCHAR==dst_type) { @@ -3028,10 +3026,7 @@ test_conv_int_1(const char *name, hid_t src, hid_t dst) hw_uchar = (unsigned char)(*((unsigned long_long*) aligned)); break; - case FLT_FLOAT: - case FLT_DOUBLE: - case FLT_LDOUBLE: - case OTHER: + default: break; } } else if (INT_SHORT==dst_type) { @@ -3084,10 +3079,7 @@ test_conv_int_1(const char *name, hid_t src, hid_t dst) hw_short = (short)(*((unsigned long_long*)aligned)); break; - case FLT_FLOAT: - case FLT_DOUBLE: - case FLT_LDOUBLE: - case OTHER: + default: break; } } else if (INT_USHORT==dst_type) { @@ -3140,10 +3132,7 @@ test_conv_int_1(const char *name, hid_t src, hid_t dst) hw_ushort = (unsigned short)(*((unsigned long_long*) aligned)); break; - case FLT_FLOAT: - case FLT_DOUBLE: - case FLT_LDOUBLE: - case OTHER: + default: break; } } else if (INT_INT==dst_type) { @@ -3195,10 +3184,7 @@ test_conv_int_1(const char *name, hid_t src, hid_t dst) sizeof(unsigned long_long)); hw_int = (int)(*((unsigned long_long*)aligned)); break; - case FLT_FLOAT: - case FLT_DOUBLE: - case FLT_LDOUBLE: - case OTHER: + default: break; } } else if (INT_UINT==dst_type) { @@ -3251,10 +3237,7 @@ test_conv_int_1(const char *name, hid_t src, hid_t dst) sizeof(unsigned long_long)); hw_uint = (unsigned int)(*((unsigned long_long*)aligned)); break; - case FLT_FLOAT: - case FLT_DOUBLE: - case FLT_LDOUBLE: - case OTHER: + default: break; } } else if (INT_LONG==dst_type) { @@ -3307,10 +3290,7 @@ test_conv_int_1(const char *name, hid_t src, hid_t dst) sizeof(unsigned long_long)); hw_long = (long int)(*((unsigned long_long*)aligned)); break; - case FLT_FLOAT: - case FLT_DOUBLE: - case FLT_LDOUBLE: - case OTHER: + default: break; } } else if (INT_ULONG==dst_type) { @@ -3364,10 +3344,7 @@ test_conv_int_1(const char *name, hid_t src, hid_t dst) hw_ulong = (unsigned long)(*((unsigned long_long*) aligned)); break; - case FLT_FLOAT: - case FLT_DOUBLE: - case FLT_LDOUBLE: - case OTHER: + default: break; } } else if (INT_LLONG==dst_type) { @@ -3420,10 +3397,7 @@ test_conv_int_1(const char *name, hid_t src, hid_t dst) sizeof(unsigned long_long)); hw_llong = (long_long)(*((unsigned long_long*)aligned)); break; - case FLT_FLOAT: - case FLT_DOUBLE: - case FLT_LDOUBLE: - case OTHER: + default: break; } } else if (INT_ULLONG==dst_type) { @@ -3481,10 +3455,7 @@ test_conv_int_1(const char *name, hid_t src, hid_t dst) hw_ullong = (unsigned long_long)(*((unsigned long_long*) aligned)); break; - case FLT_FLOAT: - case FLT_DOUBLE: - case FLT_LDOUBLE: - case OTHER: + default: break; } } @@ -3680,7 +3651,7 @@ test_conv_int_1(const char *name, hid_t src, hid_t dst) HDfprintf(stdout," %29"H5_PRINTF_LL_WIDTH"u\n", *((unsigned long_long*)aligned)); break; - case OTHER: + default: break; } @@ -3733,7 +3704,7 @@ test_conv_int_1(const char *name, hid_t src, hid_t dst) HDfprintf(stdout," %29"H5_PRINTF_LL_WIDTH"u\n", *((unsigned long_long*)aligned)); break; - case OTHER: + default: break; } @@ -3774,7 +3745,7 @@ test_conv_int_1(const char *name, hid_t src, hid_t dst) case INT_ULLONG: HDfprintf(stdout," %29"H5_PRINTF_LL_WIDTH"u\n", *((unsigned long_long*)hw)); break; - case OTHER: + default: break; } @@ -4083,7 +4054,7 @@ test_conv_int_float(const char *name, hid_t src, hid_t dst) /* * Initialize the source buffers to random bits. The `buf' buffer * will be used for the conversion while the `saved' buffer will be - * sed for the comparison later. + * used for the comparison later. */ for (j=0; j<nelmts*src_size; j++) buf[j] = saved[j] = rand(); @@ -4092,11 +4063,9 @@ test_conv_int_float(const char *name, hid_t src, hid_t dst) /* Check the results from the library against hardware */ for (j=0; j<nelmts; j++) { - /* There's a bug in my_isnan. I suspect it'll trigger some failures - * in float-float tests - * if(FLT_FLOAT==src_type || FLT_DOUBLE==src_type || FLT_LDOUBLE==src_type) - * if(my_isnan(src_type, saved+j*src_size)) - * continue;*/ + if(FLT_FLOAT==src_type || FLT_DOUBLE==src_type || FLT_LDOUBLE==src_type) + if(my_isnan(src_type, saved+j*src_size)) + continue; if (FLT_FLOAT==dst_type) { hw = (unsigned char*)&hw_float; @@ -4146,7 +4115,7 @@ test_conv_int_float(const char *name, hid_t src, hid_t dst) sizeof(unsigned long_long)); hw_float = (float)(*((unsigned long_long*)aligned)); break; - case OTHER: + default: break; } } else if (FLT_DOUBLE==dst_type) { @@ -4198,7 +4167,7 @@ test_conv_int_float(const char *name, hid_t src, hid_t dst) sizeof(unsigned long_long)); hw_double = (double)(*((unsigned long_long*)aligned)); break; - case OTHER: + default: break; } } else if (FLT_LDOUBLE==dst_type) { @@ -4256,7 +4225,7 @@ test_conv_int_float(const char *name, hid_t src, hid_t dst) hw_ldouble = (long double)(*((unsigned long_long*) aligned)); break; - case OTHER: + default: break; } } else if (INT_CHAR==dst_type) { @@ -4275,7 +4244,7 @@ test_conv_int_float(const char *name, hid_t src, hid_t dst) sizeof(long double)); hw_char = (char)(*((long double*)aligned)); break; - case OTHER: + default: break; } } else if (INT_UCHAR==dst_type) { @@ -4294,7 +4263,7 @@ test_conv_int_float(const char *name, hid_t src, hid_t dst) sizeof(long double)); hw_uchar = (unsigned char)(*((long double*)aligned)); break; - case OTHER: + default: break; } } else if (INT_SHORT==dst_type) { @@ -4313,7 +4282,7 @@ test_conv_int_float(const char *name, hid_t src, hid_t dst) sizeof(long double)); hw_short = (short)(*((long double*)aligned)); break; - case OTHER: + default: break; } } else if (INT_USHORT==dst_type) { @@ -4332,7 +4301,7 @@ test_conv_int_float(const char *name, hid_t src, hid_t dst) sizeof(long double)); hw_ushort = (unsigned short)(*((long double*)aligned)); break; - case OTHER: + default: break; } } else if (INT_INT==dst_type) { @@ -4351,7 +4320,7 @@ test_conv_int_float(const char *name, hid_t src, hid_t dst) sizeof(long double)); hw_int = (int)(*((long double*)aligned)); break; - case OTHER: + default: break; } } else if (INT_UINT==dst_type) { @@ -4370,7 +4339,7 @@ test_conv_int_float(const char *name, hid_t src, hid_t dst) sizeof(long double)); hw_uint = (unsigned int)(*((long double*)aligned)); break; - case OTHER: + default: break; } } else if (INT_LONG==dst_type) { @@ -4389,7 +4358,7 @@ test_conv_int_float(const char *name, hid_t src, hid_t dst) sizeof(long double)); hw_long = (long)(*((long double*)aligned)); break; - case OTHER: + default: break; } } else if (INT_ULONG==dst_type) { @@ -4408,7 +4377,7 @@ test_conv_int_float(const char *name, hid_t src, hid_t dst) sizeof(long double)); hw_ulong = (unsigned long)(*((long double*)aligned)); break; - case OTHER: + default: break; } } else if (INT_LLONG==dst_type) { @@ -4426,7 +4395,7 @@ test_conv_int_float(const char *name, hid_t src, hid_t dst) memcpy(aligned, saved+j*sizeof(long double), sizeof(double)); hw_llong = (long long)(*((long double*)aligned)); break; - case OTHER: + default: break; } } else if (INT_ULLONG==dst_type) { @@ -4444,17 +4413,17 @@ test_conv_int_float(const char *name, hid_t src, hid_t dst) memcpy(aligned, saved+j*sizeof(long double), sizeof(double)); hw_ullong = (unsigned long long)(*((long double*)aligned)); break; - case OTHER: + default: break; } } - /* Make certain that there isn't some weird number of destination bits */ - assert(dst_nbits%8==0); + /* Make certain that there isn't some weird number of destination bits */ + assert(dst_nbits%8==0); - /* Are the two results the same */ - for (k=(dst_size-(dst_nbits/8)); k<dst_size; k++) { - if (buf[j*dst_size+k]!=hw[k]) break; + /* Are the two results the same */ + for (k=(dst_size-(dst_nbits/8)); k<dst_size; k++) { + if (buf[j*dst_size+k]!=hw[k]) break; } if (k==dst_size) continue; /*no error*/ @@ -4768,7 +4737,7 @@ test_conv_int_float(const char *name, hid_t src, hid_t dst) * *------------------------------------------------------------------------- */ -hbool_t +static hbool_t overflows(unsigned char *origin_bits, dtype_t src_dtype, size_t src_size_bytes, size_t dst_num_bits) { hbool_t ret_value=FALSE; @@ -4779,15 +4748,14 @@ overflows(unsigned char *origin_bits, dtype_t src_dtype, size_t src_size_bytes, memcpy(bits, origin_bits, src_size_bytes); - if(src_size_bytes==4) { - frct_digits = 23; - expt_digits = 8; - bias = 0x7f; - } else if(src_size_bytes==8) { - frct_digits = 52; - expt_digits = 11; - bias = 0x3ff; + if(src_dtype==FLT_FLOAT) { + frct_digits = (FLT_MANT_DIG-1); + expt_digits = (sizeof(float)*8)-(frct_digits+1); + } else if(src_dtype==FLT_DOUBLE) { + frct_digits = (DBL_MANT_DIG-1); + expt_digits = (sizeof(double)*8)-(frct_digits+1); } + bias = (1<<(expt_digits-2)) - 1; /* get exponent */ expt = H5T_bit_get_d(bits, frct_digits, expt_digits) - bias; @@ -4814,8 +4782,6 @@ overflows(unsigned char *origin_bits, dtype_t src_dtype, size_t src_size_bytes, if(indx>=dst_num_bits) ret_value=TRUE; - free(bits); - done: return ret_value; } @@ -4881,12 +4847,8 @@ my_isnan(dtype_t type, void *val) } else { return 0; } - /* Bug here. Ought to be - * if (strstr(s, "NaN") || strstr(s, "NAN") || strstr(s, "nan")) - */ - if (!strstr(s, "NaN") || !strstr(s, "NAN") || !strstr(s, "nan")) { + if (strstr(s, "NaN") || strstr(s, "NAN") || strstr(s, "nan")) retval = 1; - } } return retval; |