From 08aa29cd5e6c4900cf6ce31d09ab44470cda0cca Mon Sep 17 00:00:00 2001 From: Raymond Lu Date: Wed, 4 Feb 2004 17:52:01 -0500 Subject: [svn-r8153] *** empty log message *** --- src/H5T.c | 1 + src/H5Tbit.c | 119 +++++++++++++++++- src/H5Tconv.c | 382 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ src/H5Tpkg.h | 7 ++ test/dtypes.c | 14 ++- 5 files changed, 517 insertions(+), 6 deletions(-) diff --git a/src/H5T.c b/src/H5T.c index f10752d..f614d32 100644 --- a/src/H5T.c +++ b/src/H5T.c @@ -955,6 +955,7 @@ H5T_init_interface(void) status |= H5T_register(H5T_PERS_SOFT, "i_i", fixedpt, fixedpt, H5T_conv_i_i, H5AC_dxpl_id); status |= H5T_register(H5T_PERS_SOFT, "f_f", floatpt, floatpt, H5T_conv_f_f, H5AC_dxpl_id); + status |= H5T_register(H5T_PERS_SOFT, "f_i", floatpt, fixedpt, H5T_conv_f_i, H5AC_dxpl_id); status |= H5T_register(H5T_PERS_SOFT, "s_s", string, string, H5T_conv_s_s, H5AC_dxpl_id); status |= H5T_register(H5T_PERS_SOFT, "b_b", bitfield, bitfield, H5T_conv_b_b, H5AC_dxpl_id); status |= H5T_register(H5T_PERS_SOFT, "ibo", fixedpt, fixedpt, H5T_conv_order, H5AC_dxpl_id); diff --git a/src/H5Tbit.c b/src/H5Tbit.c index 157da5d..d063137 100644 --- a/src/H5Tbit.c +++ b/src/H5Tbit.c @@ -78,7 +78,7 @@ H5T_bit_copy (uint8_t *dst, size_t dst_offset, const uint8_t *src, * ... v v v v v V V V V V * ...+---------------+---------------+ * ...|7 6 5 4 3 2 1 0|7 6 5 4 3 2 1 0| - * ...+---------------+---------------+ + ...+---------------+---------------+ * dst[d_idx+1] dst[d_idx] */ while (src_offset && size>0) { @@ -161,6 +161,59 @@ H5T_bit_copy (uint8_t *dst, size_t dst_offset, const uint8_t *src, /*------------------------------------------------------------------------- + * Function: H5T_bit_shift + * + * Purpose: Simulation of hardware shifting. Shifts a bit vector + * in a way similar to shifting a variable value, like + * value <<= 3, or value >>= 16. + * + * Return: void + * + * Programmer: Raymond Lu + * Wednesday, Febuary 4, 2004 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +void +H5T_bit_shift (uint8_t *buf, hssize_t shift_dist, size_t buf_size) +{ + uint8_t *tmp_buf; + size_t buf_size_bit = 8*buf_size; + size_t i; + + FUNC_ENTER_NOAPI_NOINIT(H5T_bit_shift); + + if(!shift_dist) + goto done; + if(abs(shift_dist) >= buf_size_bit) { + H5T_bit_set (buf, 0, buf_size_bit, FALSE); + goto done; + } + + tmp_buf = (uint8_t*)HDcalloc(buf_size, 1); + + /* Shift vector by making copies */ + if(shift_dist > 0) /* left shift */ + H5T_bit_copy (tmp_buf, shift_dist, buf, 0, buf_size_bit-shift_dist); + else { /* right shift */ + shift_dist = -shift_dist; + H5T_bit_copy(tmp_buf, 0, buf, shift_dist, buf_size_bit-shift_dist); + } + + /* Copy back the vector */ + for(i=0; iu.atomic.precu.atomic.prec) { H5T_bit_copy (d, dst->u.atomic.offset, s, src->u.atomic.offset, src->u.atomic.prec); + /* Why is it set to TRUE? */ H5T_bit_set (d, dst->u.atomic.offset+src->u.atomic.prec, dst->u.atomic.prec-src->u.atomic.prec, TRUE); } else { H5T_bit_copy (d, dst->u.atomic.offset, s, src->u.atomic.offset, dst->u.atomic.prec); @@ -8363,3 +8364,384 @@ H5T_conv_i32le_f64le (hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata, done: FUNC_LEAVE_NOAPI(ret_value); } + + +/*------------------------------------------------------------------------- + * Function: H5T_conv_f_i + * + * Purpose: Convert one floating-point type to an integer. This is + * the catch-all function for float-integer conversions and + * is probably not particularly fast. + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: Raymond Lu + * Wednesday, Jan 21, 2004 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +herr_t +H5T_conv_f_i (hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata, hsize_t nelmts, + size_t buf_stride, size_t UNUSED bkg_stride, void *buf, void UNUSED *bkg, + hid_t UNUSED dxpl_id) +{ + /* Traversal-related variables */ + H5T_t *src_p; /*source data type */ + H5T_t *dst_p; /*destination data type */ + H5T_atomic_t src; /*atomic source info */ + H5T_atomic_t dst; /*atomic destination info */ + int direction; /*forward or backward traversal */ + hsize_t elmtno; /*element number */ + size_t half_size; /*half the type size */ + hsize_t olap; /*num overlapping elements */ + ssize_t bitno; /*bit number */ + uint8_t *s, *sp, *d, *dp; /*source and dest traversal ptrs*/ + uint8_t dbuf[64]; /*temp destination buffer */ + + /* Conversion-related variables */ + hssize_t expo; /*source exponent */ + hssize_t mant; /*source mantissa */ + hssize_t sign; /*source sign bit value */ + uint8_t *int_buf; /*buffer for temporary value */ + size_t buf_size; /*buffer size for temporary value */ + size_t msize; /*mantissa size after restored implied 1 */ + size_t i; /*miscellaneous counters */ + size_t first; /*first bit(MSB) in an integer */ + ssize_t sfirst; /*a signed version of `first' */ + herr_t ret_value=SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI(H5T_conv_f_i, FAIL); + + switch (cdata->command) { + case H5T_CONV_INIT: + if (NULL==(src_p=H5I_object(src_id)) || + NULL==(dst_p=H5I_object(dst_id))) + HGOTO_ERROR (H5E_ARGS, H5E_BADTYPE, FAIL, "not a data type"); + src = src_p->u.atomic; + dst = dst_p->u.atomic; + if (H5T_ORDER_LE!=src.order && H5T_ORDER_BE!=src.order) + HGOTO_ERROR (H5E_DATATYPE, H5E_UNSUPPORTED, FAIL, "unsupported byte order"); + if (dst_p->size>sizeof(dbuf)) + HGOTO_ERROR (H5E_DATATYPE, H5E_UNSUPPORTED, FAIL, "destination size is too large"); + if (8*sizeof(expo)-1need_bkg = H5T_BKG_NO; + break; + + case H5T_CONV_FREE: + break; + + case H5T_CONV_CONV: + /* Get the data types */ + if (NULL==(src_p=H5I_object(src_id)) || + NULL==(dst_p=H5I_object(dst_id))) + HGOTO_ERROR (H5E_ARGS, H5E_BADTYPE, FAIL, "not a data type"); + src = src_p->u.atomic; + dst = dst_p->u.atomic; + + /* + * Do we process the values from beginning to end or vice versa? Also, + * how many of the elements have the source and destination areas + * overlapping? + */ + if (src_p->size==dst_p->size || buf_stride) { + sp = dp = (uint8_t*)buf; + direction = 1; + olap = nelmts; + } else if (src_p->size>=dst_p->size) { + double olap_d = HDceil((double)(dst_p->size)/ + (double)(src_p->size-dst_p->size)); + olap = (size_t)olap_d; + sp = dp = (uint8_t*)buf; + direction = 1; + } else { + double olap_d = HDceil((double)(src_p->size)/ + (double)(dst_p->size-src_p->size)); + olap = (size_t)olap_d; + sp = (uint8_t*)buf + (nelmts-1) * src_p->size; + dp = (uint8_t*)buf + (nelmts-1) * dst_p->size; + direction = -1; + } + + /* Allocate enough space for the buffer holding temporary + * converted value + */ + buf_size = (int)pow(2, src.u.f.esize) / 8 + 1; + int_buf = (uint8_t*)HDcalloc(buf_size, 1); + + /* The conversion loop */ + for (elmtno=0; elmtno0) { + s = sp; + d = elmtno= nelmts ? dbuf : dp; + } +#ifndef NDEBUG + /* I don't quite trust the overlap calculations yet --rpm */ + if (d==dbuf) { + assert ((dp>=sp && dpsize) || + (sp>=dp && spsize)); + } else { + assert ((dpsize<=sp) || + (spsize<=dp)); + } +#endif + /* + * Put the data in little endian order so our loops aren't so + * complicated. We'll do all the conversion stuff assuming + * little endian and then we'll fix the order at the end. + */ + if (H5T_ORDER_BE==src.order) { + half_size = src_p->size/2; + for (i=0; isize-(i+1)]; + s[src_p->size-(i+1)] = s[i]; + s[i] = tmp; + } + } + + /*zero-set all destination bits*/ + H5T_bit_set (d, dst.offset, dst.prec, FALSE); + + /* + * Find the sign bit value of the source. + */ + sign = H5T_bit_get_d(s, src.prec-1, 1); + + /* + * Check for special cases: +0, -0, +Inf, -Inf, NaN + */ + if (H5T_bit_find (s, src.u.f.mpos, src.u.f.msize, + H5T_BIT_LSB, TRUE)<0) { + if (H5T_bit_find (s, src.u.f.epos, src.u.f.esize, + H5T_BIT_LSB, TRUE)<0) { + /* +0 or -0 */ + /* Set all bits to zero */ + goto padding; + } else if (H5T_bit_find (s, src.u.f.epos, src.u.f.esize, + H5T_BIT_LSB, FALSE)<0) { + /* +Infinity or -Infinity */ + if(sign) { /* -Infinity */ + if (H5T_SGN_2==dst.u.i.sign) + H5T_bit_set (d, dst.prec-1, 1, TRUE); + } else { /* +Infinity */ + 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 (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 to zero. + */ + goto padding; + } + + /* + * Get the exponent as an unsigned quantity from the section of + * the source bit field where it's located. Not expecting + * exponent to be greater than the maximal value of hssize_t. + */ + expo = H5T_bit_get_d(s, src.u.f.epos, src.u.f.esize); + + /* + * Calculate the true source exponent by adjusting according to + * the source exponent bias. + */ + if (0==expo || H5T_NORM_NONE==src.u.f.norm) { + /*Don't get this part*/ + 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); + } else if (H5T_NORM_IMPLIED==src.u.f.norm) { + expo -= src.u.f.ebias; + } else { + assert("normalization method not implemented yet" && 0); + HDabort(); + } + + /* + * Get the mantissa as bit vector from the section of + * the source bit field where it's located. + * Keep the little-endian order in the buffer. + * A sequence 0x01020304 will be like in the buffer, + * 04 03 02 01 + * | | | | + * V V V V + * buf[0] buf[1] buf[2] buf[3] + */ + H5T_bit_copy(int_buf, 0, s, src.u.f.mpos, src.u.f.msize); + + /* + * Restore the implicit bit for mantissa if it's implied. + * Equivalent to mantissa |= (hsize_t)1<=dst.prec) { + /*overflow*/ + if (!H5T_overflow_g || (H5T_overflow_g)(src_id, dst_id, s, d)<0) { + H5T_bit_set (d, dst.offset, dst.prec, TRUE); + } + } else if (first = dst.prec-1) { + /*overflow*/ + if (!H5T_overflow_g || (H5T_overflow_g)(src_id, dst_id, s, d)<0) { + H5T_bit_set (d, dst.offset, dst.prec-1, TRUE); + } + } else if(first < dst.prec-1) { + H5T_bit_copy (d, dst.offset, int_buf, 0, first+1); + } + } + } + + /*fprintf(stderr, "dst.offset=%d, d=0x", dst.offset); + for(i=0; i0) { + assert (H5T_PAD_ZERO==dst.lsb_pad || H5T_PAD_ONE==dst.lsb_pad); + H5T_bit_set (d, 0, dst.offset, (hbool_t)(H5T_PAD_ONE==dst.lsb_pad)); + } + if (dst.offset+dst.prec!=8*dst_p->size) { + assert (H5T_PAD_ZERO==dst.msb_pad || H5T_PAD_ONE==dst.msb_pad); + H5T_bit_set (d, dst.offset+dst.prec, + 8*dst_p->size - (dst.offset+ dst.prec), + (hbool_t)(H5T_PAD_ONE==dst.msb_pad)); + } + + /* + * Put the destination in the correct byte order. See note at + * beginning of loop. + */ + if (H5T_ORDER_BE==dst.order) { + half_size = dst_p->size/2; + for (i=0; isize-(i+1)]; + d[dst_p->size-(i+1)] = d[i]; + d[i] = tmp; + } + } + + /* + * If we had used a temporary buffer for the destination then we + * should copy the value to the true destination buffer. + */ + if (d==dbuf) + HDmemcpy (dp, d, dst_p->size); + if (buf_stride) { + sp += direction * buf_stride; + dp += direction * buf_stride; + } else { + sp += direction * src_p->size; + dp += direction * dst_p->size; + } + + HDmemset(int_buf, 0, buf_size); + } + + HDfree(int_buf); + + break; + + default: + HGOTO_ERROR (H5E_DATATYPE, H5E_UNSUPPORTED, FAIL, "unknown conversion command"); + } + +done: + FUNC_LEAVE_NOAPI(ret_value); +} diff --git a/src/H5Tpkg.h b/src/H5Tpkg.h index a01d995..e068c25 100644 --- a/src/H5Tpkg.h +++ b/src/H5Tpkg.h @@ -379,6 +379,10 @@ H5_DLL herr_t H5T_conv_f_f(hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata, hsize_t nelmts, size_t buf_stride, size_t bkg_stride, void *_buf, void *bkg, hid_t dset_xfer_plist); +H5_DLL herr_t H5T_conv_f_i(hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata, + hsize_t nelmts, size_t buf_stride, + size_t bkg_stride, void *_buf, void *bkg, + hid_t dset_xfer_plist); H5_DLL herr_t H5T_conv_s_s(hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata, hsize_t nelmts, size_t buf_stride, size_t bkg_stride, void *_buf, void *bkg, @@ -1062,6 +1066,7 @@ H5_DLL herr_t H5T_conv_i32le_f64le(hid_t src_id, hid_t dst_id, /* Bit twiddling functions */ H5_DLL void H5T_bit_copy(uint8_t *dst, size_t dst_offset, const uint8_t *src, size_t src_offset, size_t size); +H5_DLL void H5T_bit_shift(uint8_t *buf, hssize_t shift_dist, size_t buf_size); H5_DLL void H5T_bit_set(uint8_t *buf, size_t offset, size_t size, hbool_t value); H5_DLL hsize_t H5T_bit_get_d(uint8_t *buf, size_t offset, size_t size); @@ -1070,6 +1075,8 @@ H5_DLL void H5T_bit_set_d(uint8_t *buf, size_t offset, size_t size, H5_DLL ssize_t H5T_bit_find(uint8_t *buf, size_t offset, size_t size, H5T_sdir_t direction, hbool_t value); H5_DLL htri_t H5T_bit_inc(uint8_t *buf, size_t start, size_t size); +H5_DLL void H5T_bit_dec(uint8_t *buf, size_t start, size_t size); +H5_DLL void H5T_bit_neg(uint8_t *buf, size_t start, size_t size); /* VL functions */ H5_DLL H5T_t * H5T_vlen_create(const H5T_t *base); diff --git a/test/dtypes.c b/test/dtypes.c index 88ddd81..8b03a68 100644 --- a/test/dtypes.c +++ b/test/dtypes.c @@ -3798,7 +3798,7 @@ test_conv_int_float(const char *name, hid_t src, hid_t dst) { const size_t ntests=NTESTS; /*number of tests */ const size_t nelmts=NTESTELEM; /*num values per test */ - const size_t max_fails=20; /*max number of failures*/ + const size_t max_fails=40; /*max number of failures*/ size_t fails_all_tests=0; /*number of failures */ size_t fails_this_test; /*fails for this test */ char str[256]; /*hello string */ @@ -4328,7 +4328,7 @@ test_conv_int_float(const char *name, hid_t src, hid_t dst) /* Make certain that there isn't some weird number of destination bits */ assert(dst_nbits%8==0); - /* Are the two results the same */ + /* Are the two results the same? */ for (k=(dst_size-(dst_nbits/8)); k