diff options
author | Raymond Lu <songyulu@hdfgroup.org> | 2005-03-22 16:12:42 (GMT) |
---|---|---|
committer | Raymond Lu <songyulu@hdfgroup.org> | 2005-03-22 16:12:42 (GMT) |
commit | b35c05cd922ca08bd8f862770109ab619a74fc22 (patch) | |
tree | a33fb14b2f59938fa0a076c85491a8e0887c569a /src | |
parent | 7730324deba4165811a9e23a47b473bef62bb464 (diff) | |
download | hdf5-b35c05cd922ca08bd8f862770109ab619a74fc22.zip hdf5-b35c05cd922ca08bd8f862770109ab619a74fc22.tar.gz hdf5-b35c05cd922ca08bd8f862770109ab619a74fc22.tar.bz2 |
[svn-r10266] Purpose: Bug fix
Description: The recent change of conversion between floating-point and floating-point types in dtypes.c have
detected some bugs in H5T_conv_f_f in H5Tconv.c.
Solution: This checkin is to fix these bugs. They happened in a few places in H5T_conv_f_f causing incorrect
rounding, denormalization, etc.
Platforms tested: h5committest and modi4
Diffstat (limited to 'src')
-rw-r--r-- | src/H5Tconv.c | 60 |
1 files changed, 29 insertions, 31 deletions
diff --git a/src/H5Tconv.c b/src/H5Tconv.c index 0016e46..4b1bf27 100644 --- a/src/H5Tconv.c +++ b/src/H5Tconv.c @@ -3377,6 +3377,7 @@ H5T_conv_f_f (hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata, size_t nelmts, hbool_t carry=0; /*carry after rounding mantissa */ size_t i; /*miscellaneous counters */ size_t implied; /*destination implied bits */ + hbool_t denormalized=FALSE; /*is either source or destination denormalized?*/ H5P_genplist_t *plist; /*property list pointer */ H5T_conv_cb_t cb_struct={NULL, NULL}; /*conversion callback structure */ H5T_conv_ret_t except_ret; /*return of callback function */ @@ -3530,7 +3531,10 @@ H5T_conv_f_f (hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata, size_t nelmts, * the exponent bias yet. */ expo = H5T_bit_get_d(s, src.u.f.epos, src.u.f.esize); - + + if(expo==0) + denormalized=TRUE; + /* * Set markers for the source mantissa, excluding the leading `1' * (might be implied). @@ -3544,8 +3548,7 @@ H5T_conv_f_f (hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata, size_t nelmts, msize = bitno; } else if (0==bitno) { msize = 1; - /* This line was moved to line 3590 */ - /*H5T_bit_set(s, src.u.f.mpos, 1, FALSE); - Why do this? */ + H5T_bit_set(s, src.u.f.mpos, 1, FALSE); } } else if (H5T_NORM_IMPLIED==src.u.f.norm) { msize = src.u.f.msize; @@ -3565,13 +3568,8 @@ H5T_conv_f_f (hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata, size_t nelmts, * the source exponent bias. */ if (0==expo || H5T_NORM_NONE==src.u.f.norm) { - bitno = H5T_bit_find(s, src.u.f.mpos, src.u.f.msize, - H5T_BIT_MSB, TRUE); assert(bitno>=0); expo -= (src.u.f.ebias-1) + (src.u.f.msize-bitno); - if(0==bitno) - /* This line was moved from line 3564 */ - H5T_bit_set(s, src.u.f.mpos, 1, FALSE); /* - Why do this? */ } else if (H5T_NORM_IMPLIED==src.u.f.norm) { expo -= src.u.f.ebias; } else { @@ -3592,12 +3590,12 @@ H5T_conv_f_f (hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata, size_t nelmts, * destination exponent values. */ expo += dst.u.f.ebias; + if (expo < -(hssize_t)(dst.u.f.msize)) { /* The exponent is way too small. Result is zero. */ expo = 0; H5T_bit_set(d, dst.u.f.mpos, dst.u.f.msize, FALSE); msize = 0; - } else if (expo<=0) { /* * The exponent is too small to fit in the exponent field, @@ -3606,9 +3604,8 @@ H5T_conv_f_f (hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata, size_t nelmts, * longer normalized. */ H5_ASSIGN_OVERFLOW(mrsh,(mrsh+1-expo),hssize_t,size_t); - /*mrsh += 1-expo;*/ expo = 0; - + denormalized=TRUE; } else if (expo>=expo_max) { /* * The exponent is too large to fit in the available region @@ -3619,7 +3616,8 @@ H5T_conv_f_f (hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata, size_t nelmts, * original byte order. */ if(cb_struct.func) { /*If user's exception handler is present, use it*/ - H5T_reverse_order(src_rev, s, src_p->shared->size, src_p->shared->u.atomic.order); /*reverse order first*/ + /*reverse order first*/ + H5T_reverse_order(src_rev, s, src_p->shared->size, src_p->shared->u.atomic.order); except_ret = (cb_struct.func)(H5T_CONV_EXCEPT_RANGE_HI, src_id, dst_id, src_rev, d, cb_struct.user_data); } @@ -3632,14 +3630,13 @@ H5T_conv_f_f (hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata, size_t nelmts, HGOTO_ERROR(H5E_DATATYPE, H5E_CANTCONVERT, FAIL, "can't handle conversion exception") else if(except_ret == H5T_CONV_HANDLED) { reverse = FALSE; - /*goto next;*/ - goto padding; + goto next; } } /* * If the destination mantissa is smaller than the source - * mantissa then round the source mantissa. Rounding may cause a + * mantissa then round the source mantissa. Rounding may cause a * carry in which case the exponent has to be re-evaluated for * overflow. That is, if `carry' is clear then the implied * mantissa bit is `1', else it is `10' binary. @@ -3647,9 +3644,18 @@ H5T_conv_f_f (hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata, size_t nelmts, if (msize>0 && mrsh<=dst.u.f.msize && mrsh+msize>dst.u.f.msize) { bitno = (ssize_t)(mrsh+msize - dst.u.f.msize); assert(bitno>=0 && (size_t)bitno<=msize); - carry = H5T_bit_inc(s, mpos+bitno-1, 1+msize-bitno); - if (carry) - implied = 2; + /*If the 1st bit being cut off is set and source isn't denormalized.*/ + if(H5T_bit_get_d(s, mpos+bitno-1, 1) && !denormalized) { + /*Don't do rounding if exponent is 111...110 and mantissa is 111...11. + *To do rounding and increment exponent in this case will create an infinity value.*/ + if((H5T_bit_find(s, mpos+bitno, msize-bitno, H5T_BIT_LSB, FALSE)>=0 || expo<expo_max-1)) { + carry = H5T_bit_inc(s, mpos+bitno-1, 1+msize-bitno); + if (carry) + implied = 2; + } + } else if(H5T_bit_get_d(s, mpos+bitno-1, 1) && denormalized) + /*For either source or destination, denormalized value doesn't increment carry.*/ + H5T_bit_inc(s, mpos+bitno-1, 1+msize-bitno); } else carry=0; @@ -3685,8 +3691,6 @@ H5T_conv_f_f (hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata, size_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) { @@ -3699,7 +3703,8 @@ H5T_conv_f_f (hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata, size_t nelmts, * buffer we hand it is in the original byte order. */ if(cb_struct.func) { /*If user's exception handler is present, use it*/ - H5T_reverse_order(src_rev, s, src_p->shared->size, src_p->shared->u.atomic.order); /*reverse order first*/ + /*reverse order first*/ + H5T_reverse_order(src_rev, s, src_p->shared->size, src_p->shared->u.atomic.order); except_ret = (cb_struct.func)(H5T_CONV_EXCEPT_RANGE_HI, src_id, dst_id, src_rev, d, cb_struct.user_data); } @@ -3711,21 +3716,15 @@ H5T_conv_f_f (hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata, size_t nelmts, HGOTO_ERROR(H5E_DATATYPE, H5E_CANTCONVERT, FAIL, "can't handle conversion exception") else if(except_ret == H5T_CONV_HANDLED) { reverse = FALSE; - /*goto next;*/ - goto padding; + goto next; } } } -#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); padding: -#ifndef LATER - /* - * Set internal padding areas - */ -#endif /* * Set external padding areas @@ -3757,7 +3756,7 @@ H5T_conv_f_f (hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata, size_t nelmts, * If we had used a temporary buffer for the destination then we * should copy the value to the true destination buffer. */ - /* next: */ + next: if (d==dbuf) HDmemcpy (dp, d, dst_p->shared->size); if (buf_stride) { @@ -9497,7 +9496,6 @@ H5T_conv_f_i (hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata, size_t nelmts, int direction; /*forward or backward traversal */ size_t elmtno; /*element number */ size_t half_size; /*half the type size */ - ssize_t bitno; /*bit number */ size_t olap; /*num overlapping elements */ uint8_t *s, *sp, *d, *dp; /*source and dest traversal ptrs*/ uint8_t *src_rev=NULL; /*order-reversed source buffer */ |