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 /src/H5T.c | |
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...
Diffstat (limited to 'src/H5T.c')
-rw-r--r-- | src/H5T.c | 178 |
1 files changed, 178 insertions, 0 deletions
@@ -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)"); |