From 2e52c2f4f26f9eab6f51eb4b12a781f383467dd4 Mon Sep 17 00:00:00 2001 From: Raymond Lu Date: Sat, 26 Mar 2005 11:16:27 -0500 Subject: [svn-r10456] Purpose: New way to do conversion test from floating-points to integers. Description: The 6th step of changing conversion test. This checkin is only for conversion of special values from floating-points to integers. Solution: This test is seperated from regular value conversion. It reuses the same function test_conv_int_float() in test/dtypes.c. The source buffer of floating-point type is filled up with 8 special values, +/-0, +/-infinity, +/-QNaN, +/-SNaN. Also added 3 new conversion exception values H5T_CONV_EXCEPT_PINF, H5T_CONV_EXCEPT_NINF, H5T_CONV_EXCEPT_NAN, for floating-point special values positive infinity, negative infinity, and NaN. These values are for conversion exception callback function defined through H5Pset_type_conv_cb(). (Remember to update the document!) Platforms tested: h5committest --- src/H5Tconv.c | 242 +++++++++++++++++++++++++++++++++++++++++++++++--------- src/H5Tpublic.h | 5 +- 2 files changed, 207 insertions(+), 40 deletions(-) diff --git a/src/H5Tconv.c b/src/H5Tconv.c index 9ebd0e8..7b1dd44 100644 --- a/src/H5Tconv.c +++ b/src/H5Tconv.c @@ -3373,6 +3373,7 @@ H5T_conv_f_f (hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata, size_t nelmts, hssize_t expo_max; /*maximum possible dst exponent */ size_t msize=0; /*useful size of mantissa in src*/ size_t mpos; /*offset to useful mant is src */ + hssize_t sign; /*source sign bit value */ size_t mrsh; /*amount to right shift mantissa*/ hbool_t carry=0; /*carry after rounding mantissa */ size_t i; /*miscellaneous counters */ @@ -3494,6 +3495,11 @@ H5T_conv_f_f (hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata, size_t nelmts, } /* + * Find the sign bit value of the source. + */ + sign = H5T_bit_get_d(s, src.u.f.sign, 1); + + /* * Check for special cases: +0, -0, +Inf, -Inf, NaN */ if (H5T_bit_find (s, src.u.f.mpos, src.u.f.msize, @@ -3508,14 +3514,33 @@ H5T_conv_f_f (hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata, size_t nelmts, } else if (H5T_bit_find (s, src.u.f.epos, src.u.f.esize, H5T_BIT_LSB, FALSE)<0) { /* +Inf or -Inf */ - H5T_bit_copy (d, dst.u.f.sign, s, src.u.f.sign, 1); - 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); - /*If the destination no implied mantissa bit, we'll need to set - *the 1st bit of mantissa to 1. The Intel-Linux long double is - *this case.*/ - if (H5T_NORM_NONE==dst.u.f.norm) - H5T_bit_set (d, dst.u.f.mpos+dst.u.f.msize-1, 1, TRUE); + if(cb_struct.func) { /*If user's exception handler is present, use it*/ + /*reverse order first*/ + H5T_reverse_order(src_rev, s, src_p->shared->size, src_p->shared->u.atomic.order); + if(sign) + except_ret = (cb_struct.func)(H5T_CONV_EXCEPT_NINF, + src_id, dst_id, src_rev, d, cb_struct.user_data); + else + except_ret = (cb_struct.func)(H5T_CONV_EXCEPT_PINF, + src_id, dst_id, src_rev, d, cb_struct.user_data); + } + + if(except_ret == H5T_CONV_UNHANDLED) { + H5T_bit_copy (d, dst.u.f.sign, s, src.u.f.sign, 1); + 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); + /*If the destination no implied mantissa bit, we'll need to set + *the 1st bit of mantissa to 1. The Intel-Linux long double is + *this case.*/ + if (H5T_NORM_NONE==dst.u.f.norm) + H5T_bit_set (d, dst.u.f.mpos+dst.u.f.msize-1, 1, TRUE); + } else if(except_ret == H5T_CONV_HANDLED) { + /*No need to reverse the order of destination because user handles it*/ + reverse = FALSE; + goto next; + } else if(except_ret == H5T_CONV_ABORT) + HGOTO_ERROR(H5E_DATATYPE, H5E_CANTCONVERT, FAIL, "can't handle conversion exception") + goto padding; } } else if (H5T_NORM_NONE==src.u.f.norm && H5T_bit_find (s, src.u.f.mpos, src.u.f.msize-1, @@ -3525,23 +3550,61 @@ H5T_conv_f_f (hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata, size_t nelmts, *If the exponent bits are all 1s and only the 1st bit of mantissa *is set to 1. It's infinity. The Intel-Linux "long double" is this case.*/ /* +Inf or -Inf */ - H5T_bit_copy (d, dst.u.f.sign, s, src.u.f.sign, 1); - 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); - /*If the destination no implied mantissa bit, we'll need to set - *the 1st bit of mantissa to 1.*/ - if (H5T_NORM_NONE==dst.u.f.norm) - H5T_bit_set (d, dst.u.f.mpos+dst.u.f.msize-1, 1, TRUE); + if(cb_struct.func) { /*If user's exception handler is present, use it*/ + /*reverse order first*/ + H5T_reverse_order(src_rev, s, src_p->shared->size, src_p->shared->u.atomic.order); + if(sign) + except_ret = (cb_struct.func)(H5T_CONV_EXCEPT_NINF, + src_id, dst_id, src_rev, d, cb_struct.user_data); + else + except_ret = (cb_struct.func)(H5T_CONV_EXCEPT_PINF, + src_id, dst_id, src_rev, d, cb_struct.user_data); + } + + if(except_ret == H5T_CONV_UNHANDLED) { + H5T_bit_copy (d, dst.u.f.sign, s, src.u.f.sign, 1); + 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); + /*If the destination no implied mantissa bit, we'll need to set + *the 1st bit of mantissa to 1. The Intel-Linux long double is + *this case.*/ + if (H5T_NORM_NONE==dst.u.f.norm) + H5T_bit_set (d, dst.u.f.mpos+dst.u.f.msize-1, 1, TRUE); + } else if(except_ret == H5T_CONV_HANDLED) { + /*No need to reverse the order of destination because user handles it*/ + reverse = FALSE; + goto next; + } else if(except_ret == H5T_CONV_ABORT) + HGOTO_ERROR(H5E_DATATYPE, H5E_CANTCONVERT, FAIL, "can't handle conversion exception") + goto padding; } else if (H5T_bit_find (s, src.u.f.epos, src.u.f.esize, H5T_BIT_LSB, FALSE)<0) { - /* - * NaN. There are many NaN values, so we just set all bits of - * the significand. - */ - H5T_bit_copy (d, dst.u.f.sign, s, src.u.f.sign, 1); - 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, TRUE); + /* NaN */ + if(cb_struct.func) { /*If user's exception handler is present, use it*/ + /*reverse order first*/ + H5T_reverse_order(src_rev, s, src_p->shared->size, src_p->shared->u.atomic.order); + if(sign) + except_ret = (cb_struct.func)(H5T_CONV_EXCEPT_NINF, + src_id, dst_id, src_rev, d, cb_struct.user_data); + else + except_ret = (cb_struct.func)(H5T_CONV_EXCEPT_PINF, + src_id, dst_id, src_rev, d, cb_struct.user_data); + } + + if(except_ret == H5T_CONV_UNHANDLED) { + /* There are many NaN values, so we just set all bits of + * the significand. */ + H5T_bit_copy (d, dst.u.f.sign, s, src.u.f.sign, 1); + 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, TRUE); + } else if(except_ret == H5T_CONV_HANDLED) { + /*No need to reverse the order of destination because user handles it*/ + reverse = FALSE; + goto next; + } else if(except_ret == H5T_CONV_ABORT) + HGOTO_ERROR(H5E_DATATYPE, H5E_CANTCONVERT, FAIL, "can't handle conversion exception") + goto padding; } @@ -9670,21 +9733,109 @@ H5T_conv_f_i (hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata, size_t nelmts, H5T_BIT_LSB, FALSE)<0) { /* +Infinity or -Infinity */ if(sign) { /* -Infinity */ + if(cb_struct.func) { /*If user's exception handler is present, use it*/ + /*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_NINF, + src_id, dst_id, src_rev, d, cb_struct.user_data); + } + + if(except_ret == H5T_CONV_UNHANDLED) { + if (H5T_SGN_2==dst.u.i.sign) + H5T_bit_set (d, dst.prec-1, 1, TRUE); + } else if(except_ret == H5T_CONV_HANDLED) { + /*No need to reverse the order of destination because user handles it*/ + reverse = FALSE; + goto next; + } else if(except_ret == H5T_CONV_ABORT) + HGOTO_ERROR(H5E_DATATYPE, H5E_CANTCONVERT, FAIL, "can't handle conversion exception") + } else { /* +Infinity */ + if(cb_struct.func) { /*If user's exception handler is present, use it*/ + /*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_PINF, + src_id, dst_id, src_rev, d, cb_struct.user_data); + } + + if(except_ret == H5T_CONV_UNHANDLED) { + if (H5T_SGN_NONE==dst.u.i.sign) + H5T_bit_set (d, dst.offset, dst.prec, TRUE); + else if (H5T_SGN_2==dst.u.i.sign) + H5T_bit_set (d, dst.offset, dst.prec-1, TRUE); + } else if(except_ret == H5T_CONV_HANDLED) { + /*No need to reverse the order of destination because user handles it*/ + reverse = FALSE; + goto next; + } else if(except_ret == H5T_CONV_ABORT) + HGOTO_ERROR(H5E_DATATYPE, H5E_CANTCONVERT, FAIL, "can't handle conversion exception") + } + goto padding; + } + } else if (H5T_NORM_NONE==src.u.f.norm && H5T_bit_find (s, src.u.f.mpos, src.u.f.msize-1, + H5T_BIT_LSB, TRUE)<0 && H5T_bit_find (s, src.u.f.epos, src.u.f.esize, + H5T_BIT_LSB, FALSE)<0) { + /*This is a special case for the source of no implied mantissa bit. + *If the exponent bits are all 1s and only the 1st bit of mantissa + *is set to 1. It's infinity. The Intel-Linux "long double" is this case.*/ + /* +Infinity or -Infinity */ + if(sign) { /* -Infinity */ + if(cb_struct.func) { /*If user's exception handler is present, use it*/ + /*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_NINF, + src_id, dst_id, src_rev, d, cb_struct.user_data); + } + + if(except_ret == H5T_CONV_UNHANDLED) { if (H5T_SGN_2==dst.u.i.sign) H5T_bit_set (d, dst.prec-1, 1, TRUE); - } else { /* +Infinity */ + } else if(except_ret == H5T_CONV_HANDLED) { + /*No need to reverse the order of destination because user handles it*/ + reverse = FALSE; + goto next; + } else if(except_ret == H5T_CONV_ABORT) + HGOTO_ERROR(H5E_DATATYPE, H5E_CANTCONVERT, FAIL, "can't handle conversion exception") + } else { /* +Infinity */ + if(cb_struct.func) { /*If user's exception handler is present, use it*/ + /*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_PINF, + src_id, dst_id, src_rev, d, cb_struct.user_data); + } + + if(except_ret == H5T_CONV_UNHANDLED) { if (H5T_SGN_NONE==dst.u.i.sign) H5T_bit_set (d, dst.offset, dst.prec, TRUE); else if (H5T_SGN_2==dst.u.i.sign) H5T_bit_set (d, dst.offset, dst.prec-1, TRUE); - } - goto padding; - } + } else if(except_ret == H5T_CONV_HANDLED) { + /*No need to reverse the order of destination because user handles it*/ + reverse = FALSE; + goto next; + } else if(except_ret == H5T_CONV_ABORT) + HGOTO_ERROR(H5E_DATATYPE, H5E_CANTCONVERT, FAIL, "can't handle conversion exception") + } + goto padding; } else if (H5T_bit_find (s, src.u.f.epos, src.u.f.esize, H5T_BIT_LSB, FALSE)<0) { - /* - * NaN. Just set all bits to zero. - */ + /* NaN */ + if(cb_struct.func) { /*If user's exception handler is present, use it*/ + /*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_NAN, + src_id, dst_id, src_rev, d, cb_struct.user_data); + } + + if(except_ret == H5T_CONV_UNHANDLED) { + /*Just set all bits to zero.*/ + goto padding; + } else if(except_ret == H5T_CONV_HANDLED) { + /*No need to reverse the order of destination because user handles it*/ + reverse = FALSE; + goto next; + } else if(except_ret == H5T_CONV_ABORT) + HGOTO_ERROR(H5E_DATATYPE, H5E_CANTCONVERT, FAIL, "can't handle conversion exception") + goto padding; } @@ -9771,9 +9922,11 @@ H5T_conv_f_i (hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata, size_t nelmts, src_id, dst_id, src_rev, d, cb_struct.user_data); if(except_ret == H5T_CONV_ABORT) HGOTO_ERROR(H5E_DATATYPE, H5E_CANTCONVERT, FAIL, "can't handle conversion exception") - else if(except_ret == H5T_CONV_HANDLED) + else if(except_ret == H5T_CONV_HANDLED) { /*No need to reverse the order of destination because user handles it*/ reverse = FALSE; + goto next; + } } } else { /*source is positive*/ if (first>=dst.prec) { @@ -9786,10 +9939,11 @@ H5T_conv_f_i (hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata, size_t nelmts, if(except_ret == H5T_CONV_UNHANDLED) H5T_bit_set (d, dst.offset, dst.prec, TRUE); - else if(except_ret == H5T_CONV_HANDLED) + else if(except_ret == H5T_CONV_HANDLED) { /*No need to reverse the order of destination because user handles it*/ reverse = FALSE; - else if(except_ret == H5T_CONV_ABORT) + goto next; + } else if(except_ret == H5T_CONV_ABORT) HGOTO_ERROR(H5E_DATATYPE, H5E_CANTCONVERT, FAIL, "can't handle conversion exception") } else if (first = dst.prec-1) { @@ -9863,9 +10022,11 @@ H5T_conv_f_i (hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata, size_t nelmts, H5T_bit_set (d, dst.offset, dst.prec-1, TRUE); else if(except_ret == H5T_CONV_ABORT) HGOTO_ERROR(H5E_DATATYPE, H5E_CANTCONVERT, FAIL, "can't handle conversion exception") - else if(except_ret == H5T_CONV_HANDLED) + else if(except_ret == H5T_CONV_HANDLED) { /*No need to reverse the order of destination because user handles it*/ reverse = FALSE; + goto next; + } } else if(first < dst.prec-1) { if(truncated && cb_struct.func) { /*If user's exception handler is present, use it*/ /*reverse order first*/ @@ -9879,9 +10040,11 @@ H5T_conv_f_i (hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata, size_t nelmts, H5T_bit_copy (d, dst.offset, int_buf, 0, first+1); } else if(except_ret == H5T_CONV_ABORT) HGOTO_ERROR(H5E_DATATYPE, H5E_CANTCONVERT, FAIL, "can't handle conversion exception") - else if(except_ret == H5T_CONV_HANDLED) + else if(except_ret == H5T_CONV_HANDLED) { /*No need to reverse the order of destination because user handles it*/ reverse = FALSE; + goto next; + } } } } @@ -9913,7 +10076,8 @@ H5T_conv_f_i (hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata, size_t nelmts, d[i] = tmp; } } - + + next: /* * If we had used a temporary buffer for the destination then we * should copy the value to the true destination buffer. diff --git a/src/H5Tpublic.h b/src/H5Tpublic.h index ddec8bb..98e92d3 100644 --- a/src/H5Tpublic.h +++ b/src/H5Tpublic.h @@ -172,7 +172,10 @@ typedef enum H5T_conv_except_t { H5T_CONV_EXCEPT_RANGE_HI = 0, /*source value is greater than destination's range */ H5T_CONV_EXCEPT_RANGE_LOW = 1, /*source value is less than destination's range */ H5T_CONV_EXCEPT_PRECISION = 2, /*source value loses precision in destination */ - H5T_CONV_EXCEPT_TRUNCATE = 3 /*source value is truncated in destination */ + H5T_CONV_EXCEPT_TRUNCATE = 3, /*source value is truncated in destination */ + H5T_CONV_EXCEPT_PINF = 4, /*source value is positive infinity(floating number) */ + H5T_CONV_EXCEPT_NINF = 5, /*source value is negative infinity(floating number) */ + H5T_CONV_EXCEPT_NAN = 6 /*source value is NaN(floating number) */ } H5T_conv_except_t; /* The return value from conversion callback function H5T_conv_except_func_t */ -- cgit v0.12