summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorRaymond Lu <songyulu@hdfgroup.org>2005-03-22 16:12:42 (GMT)
committerRaymond Lu <songyulu@hdfgroup.org>2005-03-22 16:12:42 (GMT)
commitb35c05cd922ca08bd8f862770109ab619a74fc22 (patch)
treea33fb14b2f59938fa0a076c85491a8e0887c569a /src
parent7730324deba4165811a9e23a47b473bef62bb464 (diff)
downloadhdf5-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.c60
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 */