diff --git a/src/H5Tconv.c b/src/H5Tconv.c index 688eb606bd..7d77914337 100644 --- a/src/H5Tconv.c +++ b/src/H5Tconv.c @@ -163,6 +163,11 @@ H5FL_BLK_DEFINE_STATIC(array_seq); * is invoked inside the H5T_CONV "template" macro by "gluing" it together, * which allows the core conversion macro to be invoked as necessary. * + * "Core" macros come in two flavors: one which calls the exception handling + * routine and one which doesn't (the "_NOEX" variant). The presence of the + * exception handling routine is detected before the loop over the values and + * the appropriate core routine loop is executed. + * * The generic "core" macros are: (others are specific to particular conversion) * * Suffix Description @@ -179,7 +184,10 @@ H5FL_BLK_DEFINE_STATIC(array_seq); * destination. * */ -#define H5T_CONV_xX_CORE(S,D,STYPE,DTYPE,ST,DT,D_MIN,D_MAX) { \ +#define H5T_CONV_xX_CORE(S,D,ST,DT,D_MIN,D_MAX,D_PREC) { \ + *((DT*)D) = (DT)(*((ST*)S)); \ +} +#define H5T_CONV_xX_NOEX_CORE(S,D,ST,DT,D_MIN,D_MAX,D_PREC) { \ *((DT*)D) = (DT)(*((ST*)S)); \ } @@ -190,293 +198,335 @@ H5FL_BLK_DEFINE_STATIC(array_seq); * equal. In this case, do not return exception but make sure the maximum is assigned * to the destination. SLU - 2005/06/29 */ -#define H5T_CONV_Xx_CORE(S,D,STYPE,DTYPE,ST,DT,D_MIN,D_MAX) { \ +#define H5T_CONV_Xx_CORE(S,D,ST,DT,D_MIN,D_MAX,D_PREC) { \ if (*((ST*)S) > (DT)(D_MAX)) { \ - if(cb_struct.func) { \ - H5T_conv_ret_t except_ret; /*callback return*/ \ - \ - except_ret = (cb_struct.func)(H5T_CONV_EXCEPT_RANGE_HI, \ - src_id, dst_id, S, D, cb_struct.user_data); \ - if(except_ret == H5T_CONV_UNHANDLED) \ - /* Let compiler convert if case is ignored by user handler*/ \ - *((DT*)D) = (D_MAX); \ - else if(except_ret == H5T_CONV_ABORT) \ - HGOTO_ERROR(H5E_DATATYPE, H5E_CANTCONVERT, FAIL, "can't handle conversion exception") \ - /* if(except_ret==H5T_CONV_HANDLED): Fall through, user handled it */ \ - } \ - else \ + H5T_conv_ret_t except_ret = (cb_struct.func)(H5T_CONV_EXCEPT_RANGE_HI, \ + src_id, dst_id, S, D, cb_struct.user_data); \ + if(except_ret == H5T_CONV_UNHANDLED) \ + /* Let compiler convert if case is ignored by user handler*/ \ *((DT*)D) = (D_MAX); \ + else if(except_ret == H5T_CONV_ABORT) \ + HGOTO_ERROR(H5E_DATATYPE, H5E_CANTCONVERT, FAIL, "can't handle conversion exception") \ + /* if(except_ret==H5T_CONV_HANDLED): Fall through, user handled it */ \ } else if (*((ST*)S) < (DT)(D_MIN)) { \ - if(cb_struct.func) { \ - H5T_conv_ret_t except_ret; /*callback return*/ \ - \ - except_ret = (cb_struct.func)(H5T_CONV_EXCEPT_RANGE_LOW, \ - src_id, dst_id, S, D, cb_struct.user_data); \ - if(except_ret == H5T_CONV_UNHANDLED) \ - /* Let compiler convert if case is ignored by user handler*/ \ - *((DT*)D) = (D_MIN); \ - else if(except_ret == H5T_CONV_ABORT) \ - HGOTO_ERROR(H5E_DATATYPE, H5E_CANTCONVERT, FAIL, "can't handle conversion exception") \ - /* if(except_ret==H5T_CONV_HANDLED): Fall through, user handled it */ \ - } \ - else \ + H5T_conv_ret_t except_ret = (cb_struct.func)(H5T_CONV_EXCEPT_RANGE_LOW, \ + src_id, dst_id, S, D, cb_struct.user_data); \ + if(except_ret == H5T_CONV_UNHANDLED) \ + /* Let compiler convert if case is ignored by user handler*/ \ *((DT*)D) = (D_MIN); \ + else if(except_ret == H5T_CONV_ABORT) \ + HGOTO_ERROR(H5E_DATATYPE, H5E_CANTCONVERT, FAIL, "can't handle conversion exception") \ + /* if(except_ret==H5T_CONV_HANDLED): Fall through, user handled it */ \ + } else \ + *((DT*)D) = (DT)(*((ST*)S)); \ +} +#define H5T_CONV_Xx_NOEX_CORE(S,D,ST,DT,D_MIN,D_MAX,D_PREC) { \ + if (*((ST*)S) > (DT)(D_MAX)) { \ + *((DT*)D) = (D_MAX); \ + } else if (*((ST*)S) < (DT)(D_MIN)) { \ + *((DT*)D) = (D_MIN); \ } else \ *((DT*)D) = (DT)(*((ST*)S)); \ } -#define H5T_CONV_Ux_CORE(S,D,STYPE,DTYPE,ST,DT,D_MIN,D_MAX) { \ +#define H5T_CONV_Ux_CORE(S,D,ST,DT,D_MIN,D_MAX,D_PREC) { \ if (*((ST*)S) > (DT)(D_MAX)) { \ - if(cb_struct.func) { \ - H5T_conv_ret_t except_ret; /*callback return*/ \ - \ - except_ret = (cb_struct.func)(H5T_CONV_EXCEPT_RANGE_HI, \ - src_id, dst_id, S, D, cb_struct.user_data); \ - if(except_ret == H5T_CONV_UNHANDLED) \ - /* Let compiler convert if case is ignored by user handler*/ \ - *((DT*)D) = (D_MAX); \ - else if(except_ret == H5T_CONV_ABORT) \ - HGOTO_ERROR(H5E_DATATYPE, H5E_CANTCONVERT, FAIL, "can't handle conversion exception") \ - /* if(except_ret==H5T_CONV_HANDLED): Fall through, user handled it */ \ - } \ - else \ + H5T_conv_ret_t except_ret = (cb_struct.func)(H5T_CONV_EXCEPT_RANGE_HI, \ + src_id, dst_id, S, D, cb_struct.user_data); \ + if(except_ret == H5T_CONV_UNHANDLED) \ + /* Let compiler convert if case is ignored by user handler*/ \ *((DT*)D) = (D_MAX); \ + else if(except_ret == H5T_CONV_ABORT) \ + HGOTO_ERROR(H5E_DATATYPE, H5E_CANTCONVERT, FAIL, "can't handle conversion exception") \ + /* if(except_ret==H5T_CONV_HANDLED): Fall through, user handled it */ \ + } else \ + *((DT*)D) = (DT)(*((ST*)S)); \ +} +#define H5T_CONV_Ux_NOEX_CORE(S,D,ST,DT,D_MIN,D_MAX,D_PREC) { \ + if (*((ST*)S) > (DT)(D_MAX)) { \ + *((DT*)D) = (D_MAX); \ } else \ *((DT*)D) = (DT)(*((ST*)S)); \ } -#define H5T_CONV_sS(STYPE,DTYPE,ST,DT,D_MIN,D_MAX) { \ +#define H5T_CONV_sS(STYPE,DTYPE,ST,DT,D_MIN,D_MAX,D_PREC) { \ assert(sizeof(ST)<=sizeof(DT)); \ - H5T_CONV(H5T_CONV_xX, long_long, STYPE, DTYPE, ST, DT, D_MIN, D_MAX) \ + H5T_CONV(H5T_CONV_xX, long_long, STYPE, DTYPE, ST, DT, D_MIN, D_MAX, D_PREC) \ } -#define H5T_CONV_sU_CORE(S,D,STYPE,DTYPE,ST,DT,D_MIN,D_MAX) { \ +#define H5T_CONV_sU_CORE(S,D,ST,DT,D_MIN,D_MAX,D_PREC) { \ if (*((ST*)S) < 0) { \ - if(cb_struct.func) { \ - H5T_conv_ret_t except_ret; /*callback return*/ \ - \ - except_ret = (cb_struct.func)(H5T_CONV_EXCEPT_RANGE_LOW, \ - src_id, dst_id, S, D, cb_struct.user_data); \ - if(except_ret == H5T_CONV_UNHANDLED) \ - /* Let compiler convert if case is ignored by user handler*/ \ - *((DT*)D) = 0; \ - else if(except_ret == H5T_CONV_ABORT) \ - HGOTO_ERROR(H5E_DATATYPE, H5E_CANTCONVERT, FAIL, "can't handle conversion exception") \ - /* if(except_ret==H5T_CONV_HANDLED): Fall through, user handled it */ \ - } \ - else \ + H5T_conv_ret_t except_ret = (cb_struct.func)(H5T_CONV_EXCEPT_RANGE_LOW, \ + src_id, dst_id, S, D, cb_struct.user_data); \ + if(except_ret == H5T_CONV_UNHANDLED) \ + /* Let compiler convert if case is ignored by user handler*/ \ *((DT*)D) = 0; \ + else if(except_ret == H5T_CONV_ABORT) \ + HGOTO_ERROR(H5E_DATATYPE, H5E_CANTCONVERT, FAIL, "can't handle conversion exception") \ + /* if(except_ret==H5T_CONV_HANDLED): Fall through, user handled it */ \ + } else \ + *((DT*)D) = (DT)(*((ST*)S)); \ +} +#define H5T_CONV_sU_NOEX_CORE(S,D,ST,DT,D_MIN,D_MAX,D_PREC) { \ + if (*((ST*)S) < 0) { \ + *((DT*)D) = 0; \ } else \ *((DT*)D) = (DT)(*((ST*)S)); \ } -#define H5T_CONV_sU(STYPE,DTYPE,ST,DT,D_MIN,D_MAX) { \ +#define H5T_CONV_sU(STYPE,DTYPE,ST,DT,D_MIN,D_MAX,D_PREC) { \ assert(sizeof(ST)<=sizeof(DT)); \ - H5T_CONV(H5T_CONV_sU, long_long, STYPE, DTYPE, ST, DT, D_MIN, D_MAX) \ + H5T_CONV(H5T_CONV_sU, long_long, STYPE, DTYPE, ST, DT, D_MIN, D_MAX, D_PREC) \ } -#define H5T_CONV_uS_CORE(S,D,STYPE,DTYPE,ST,DT,D_MIN,D_MAX) { \ +#define H5T_CONV_uS_CORE(S,D,ST,DT,D_MIN,D_MAX,D_PREC) { \ if (sizeof(ST)==sizeof(DT) && *((ST*)S) > (D_MAX)) { \ - if(cb_struct.func) { \ - H5T_conv_ret_t except_ret; /*callback return*/ \ - \ - except_ret = (cb_struct.func)(H5T_CONV_EXCEPT_RANGE_HI, \ - src_id, dst_id, S, D, cb_struct.user_data); \ - if(except_ret == H5T_CONV_UNHANDLED) \ - /* Let compiler convert if case is ignored by user handler*/ \ - *((DT*)D) = (D_MAX); \ - else if(except_ret == H5T_CONV_ABORT) \ - HGOTO_ERROR(H5E_DATATYPE, H5E_CANTCONVERT, FAIL, "can't handle conversion exception") \ - /* if(except_ret==H5T_CONV_HANDLED): Fall through, user handled it */ \ - } \ - else \ + H5T_conv_ret_t except_ret = (cb_struct.func)(H5T_CONV_EXCEPT_RANGE_HI, \ + src_id, dst_id, S, D, cb_struct.user_data); \ + if(except_ret == H5T_CONV_UNHANDLED) \ + /* Let compiler convert if case is ignored by user handler*/ \ *((DT*)D) = (D_MAX); \ + else if(except_ret == H5T_CONV_ABORT) \ + HGOTO_ERROR(H5E_DATATYPE, H5E_CANTCONVERT, FAIL, "can't handle conversion exception") \ + /* if(except_ret==H5T_CONV_HANDLED): Fall through, user handled it */ \ + } else \ + *((DT*)D) = (DT)(*((ST*)S)); \ +} +#define H5T_CONV_uS_NOEX_CORE(S,D,ST,DT,D_MIN,D_MAX,D_PREC) { \ + if (sizeof(ST)==sizeof(DT) && *((ST*)S) > (D_MAX)) { \ + *((DT*)D) = (D_MAX); \ } else \ *((DT*)D) = (DT)(*((ST*)S)); \ } -#define H5T_CONV_uS(STYPE,DTYPE,ST,DT,D_MIN,D_MAX) { \ +#define H5T_CONV_uS(STYPE,DTYPE,ST,DT,D_MIN,D_MAX,D_PREC) { \ assert(sizeof(ST)<=sizeof(DT)); \ - H5T_CONV(H5T_CONV_uS, long_long, STYPE, DTYPE, ST, DT, D_MIN, D_MAX) \ + H5T_CONV(H5T_CONV_uS, long_long, STYPE, DTYPE, ST, DT, D_MIN, D_MAX, D_PREC) \ } -#define H5T_CONV_uU(STYPE,DTYPE,ST,DT,D_MIN,D_MAX) { \ +#define H5T_CONV_uU(STYPE,DTYPE,ST,DT,D_MIN,D_MAX,D_PREC) { \ assert(sizeof(ST)<=sizeof(DT)); \ - H5T_CONV(H5T_CONV_xX, long_long, STYPE, DTYPE, ST, DT, D_MIN, D_MAX) \ + H5T_CONV(H5T_CONV_xX, long_long, STYPE, DTYPE, ST, DT, D_MIN, D_MAX, D_PREC) \ } -#define H5T_CONV_Ss(STYPE,DTYPE,ST,DT,D_MIN,D_MAX) { \ +#define H5T_CONV_Ss(STYPE,DTYPE,ST,DT,D_MIN,D_MAX,D_PREC) { \ assert(sizeof(ST)>=sizeof(DT)); \ - H5T_CONV(H5T_CONV_Xx, long_long, STYPE, DTYPE, ST, DT, D_MIN, D_MAX) \ + H5T_CONV(H5T_CONV_Xx, long_long, STYPE, DTYPE, ST, DT, D_MIN, D_MAX, D_PREC) \ } -#define H5T_CONV_Su_CORE(S,D,STYPE,DTYPE,ST,DT,D_MIN,D_MAX) { \ +#define H5T_CONV_Su_CORE(S,D,ST,DT,D_MIN,D_MAX,D_PREC) { \ if (*((ST*)S) < 0) { \ - if(cb_struct.func) { \ - H5T_conv_ret_t except_ret; /*callback return*/ \ - \ - except_ret = (cb_struct.func)(H5T_CONV_EXCEPT_RANGE_LOW, \ - src_id, dst_id, S, D, cb_struct.user_data); \ - if(except_ret == H5T_CONV_UNHANDLED) \ - /* Let compiler convert if case is ignored by user handler*/ \ - *((DT*)D) = 0; \ - else if(except_ret == H5T_CONV_ABORT) \ - HGOTO_ERROR(H5E_DATATYPE, H5E_CANTCONVERT, FAIL, "can't handle conversion exception") \ - /* if(except_ret==H5T_CONV_HANDLED): Fall through, user handled it */ \ - } \ - else \ + H5T_conv_ret_t except_ret = (cb_struct.func)(H5T_CONV_EXCEPT_RANGE_LOW, \ + src_id, dst_id, S, D, cb_struct.user_data); \ + if(except_ret == H5T_CONV_UNHANDLED) \ + /* Let compiler convert if case is ignored by user handler*/ \ *((DT*)D) = 0; \ + else if(except_ret == H5T_CONV_ABORT) \ + HGOTO_ERROR(H5E_DATATYPE, H5E_CANTCONVERT, FAIL, "can't handle conversion exception") \ + /* if(except_ret==H5T_CONV_HANDLED): Fall through, user handled it */ \ } else if (sizeof(ST)>sizeof(DT) && *((ST*)S) > (DT)(D_MAX)) { \ - if(cb_struct.func) { \ - H5T_conv_ret_t except_ret; /*callback return*/ \ - \ - except_ret = (cb_struct.func)(H5T_CONV_EXCEPT_RANGE_HI, \ - src_id, dst_id, S, D, cb_struct.user_data); \ - if(except_ret == H5T_CONV_UNHANDLED) \ - /* Let compiler convert if case is ignored by user handler*/ \ - *((DT*)D) = (D_MAX); \ - else if(except_ret == H5T_CONV_ABORT) \ - HGOTO_ERROR(H5E_DATATYPE, H5E_CANTCONVERT, FAIL, "can't handle conversion exception") \ - /* if(except_ret==H5T_CONV_HANDLED): Fall through, user handled it */ \ - } \ - else \ + H5T_conv_ret_t except_ret = (cb_struct.func)(H5T_CONV_EXCEPT_RANGE_HI, \ + src_id, dst_id, S, D, cb_struct.user_data); \ + if(except_ret == H5T_CONV_UNHANDLED) \ + /* Let compiler convert if case is ignored by user handler*/ \ *((DT*)D) = (D_MAX); \ + else if(except_ret == H5T_CONV_ABORT) \ + HGOTO_ERROR(H5E_DATATYPE, H5E_CANTCONVERT, FAIL, "can't handle conversion exception") \ + /* if(except_ret==H5T_CONV_HANDLED): Fall through, user handled it */ \ + } else \ + *((DT*)D) = (DT)(*((ST*)S)); \ +} +#define H5T_CONV_Su_NOEX_CORE(S,D,ST,DT,D_MIN,D_MAX,D_PREC) { \ + if (*((ST*)S) < 0) { \ + *((DT*)D) = 0; \ + } else if (sizeof(ST)>sizeof(DT) && *((ST*)S) > (DT)(D_MAX)) { \ + *((DT*)D) = (D_MAX); \ } else \ *((DT*)D) = (DT)(*((ST*)S)); \ } -#define H5T_CONV_Su(STYPE,DTYPE,ST,DT,D_MIN,D_MAX) { \ +#define H5T_CONV_Su(STYPE,DTYPE,ST,DT,D_MIN,D_MAX,D_PREC) { \ assert(sizeof(ST)>=sizeof(DT)); \ - H5T_CONV(H5T_CONV_Su, long_long, STYPE, DTYPE, ST, DT, D_MIN, D_MAX) \ + H5T_CONV(H5T_CONV_Su, long_long, STYPE, DTYPE, ST, DT, D_MIN, D_MAX, D_PREC) \ } -#define H5T_CONV_Us(STYPE,DTYPE,ST,DT,D_MIN,D_MAX) { \ +#define H5T_CONV_Us(STYPE,DTYPE,ST,DT,D_MIN,D_MAX,D_PREC) { \ assert(sizeof(ST)>=sizeof(DT)); \ - H5T_CONV(H5T_CONV_Ux, long_long, STYPE, DTYPE, ST, DT, D_MIN, D_MAX) \ + H5T_CONV(H5T_CONV_Ux, long_long, STYPE, DTYPE, ST, DT, D_MIN, D_MAX, D_PREC) \ } -#define H5T_CONV_Uu(STYPE,DTYPE,ST,DT,D_MIN,D_MAX) { \ +#define H5T_CONV_Uu(STYPE,DTYPE,ST,DT,D_MIN,D_MAX,D_PREC) { \ assert(sizeof(ST)>=sizeof(DT)); \ - H5T_CONV(H5T_CONV_Ux, long_long, STYPE, DTYPE, ST, DT, D_MIN, D_MAX) \ + H5T_CONV(H5T_CONV_Ux, long_long, STYPE, DTYPE, ST, DT, D_MIN, D_MAX, D_PREC) \ } -#define H5T_CONV_su_CORE(S,D,STYPE,DTYPE,ST,DT,D_MIN,D_MAX) { \ +#define H5T_CONV_su_CORE(S,D,ST,DT,D_MIN,D_MAX,D_PREC) { \ /* Assumes memory format of unsigned & signed integers is same */ \ if (*((ST*)S) < 0) { \ - if(cb_struct.func) { \ - H5T_conv_ret_t except_ret; /*callback return*/ \ - \ - except_ret = (cb_struct.func)(H5T_CONV_EXCEPT_RANGE_LOW, \ - src_id, dst_id, S, D, cb_struct.user_data); \ - if(except_ret == H5T_CONV_UNHANDLED) \ - /* Let compiler convert if case is ignored by user handler*/ \ - *((DT*)D) = 0; \ - else if(except_ret == H5T_CONV_ABORT) \ - HGOTO_ERROR(H5E_DATATYPE, H5E_CANTCONVERT, FAIL, "can't handle conversion exception") \ - /* if(except_ret==H5T_CONV_HANDLED): Fall through, user handled it */ \ - } \ - else \ + H5T_conv_ret_t except_ret = (cb_struct.func)(H5T_CONV_EXCEPT_RANGE_LOW, \ + src_id, dst_id, S, D, cb_struct.user_data); \ + if(except_ret == H5T_CONV_UNHANDLED) \ + /* Let compiler convert if case is ignored by user handler*/ \ *((DT*)D) = 0; \ + else if(except_ret == H5T_CONV_ABORT) \ + HGOTO_ERROR(H5E_DATATYPE, H5E_CANTCONVERT, FAIL, "can't handle conversion exception") \ + /* if(except_ret==H5T_CONV_HANDLED): Fall through, user handled it */ \ + } else \ + *((DT*)D) = (DT)(*((ST*)S)); \ +} +#define H5T_CONV_su_NOEX_CORE(S,D,ST,DT,D_MIN,D_MAX,D_PREC) { \ + /* Assumes memory format of unsigned & signed integers is same */ \ + if (*((ST*)S) < 0) { \ + *((DT*)D) = 0; \ } else \ *((DT*)D) = (DT)(*((ST*)S)); \ } -#define H5T_CONV_su(STYPE,DTYPE,ST,DT,D_MIN,D_MAX) { \ +#define H5T_CONV_su(STYPE,DTYPE,ST,DT,D_MIN,D_MAX,D_PREC) { \ assert(sizeof(ST)==sizeof(DT)); \ - H5T_CONV(H5T_CONV_su, long_long, STYPE, DTYPE, ST, DT, D_MIN, D_MAX) \ + H5T_CONV(H5T_CONV_su, long_long, STYPE, DTYPE, ST, DT, D_MIN, D_MAX, D_PREC) \ } -#define H5T_CONV_us_CORE(S,D,STYPE,DTYPE,ST,DT,D_MIN,D_MAX) { \ +#define H5T_CONV_us_CORE(S,D,ST,DT,D_MIN,D_MAX,D_PREC) { \ /* Assumes memory format of unsigned & signed integers is same */ \ if (*((ST*)S) > (DT)(D_MAX)) { \ - if(cb_struct.func) { \ - H5T_conv_ret_t except_ret; /*callback return*/ \ - \ - except_ret = (cb_struct.func)(H5T_CONV_EXCEPT_RANGE_HI, \ - src_id, dst_id, S, D, cb_struct.user_data); \ - if(except_ret == H5T_CONV_UNHANDLED) \ - /* Let compiler convert if case is ignored by user handler*/ \ - *((DT*)D) = (D_MAX); \ - else if(except_ret == H5T_CONV_ABORT) \ - HGOTO_ERROR(H5E_DATATYPE, H5E_CANTCONVERT, FAIL, "can't handle conversion exception") \ - /* if(except_ret==H5T_CONV_HANDLED): Fall through, user handled it */ \ - } \ - else \ + H5T_conv_ret_t except_ret = (cb_struct.func)(H5T_CONV_EXCEPT_RANGE_HI, \ + src_id, dst_id, S, D, cb_struct.user_data); \ + if(except_ret == H5T_CONV_UNHANDLED) \ + /* Let compiler convert if case is ignored by user handler*/ \ *((DT*)D) = (D_MAX); \ + else if(except_ret == H5T_CONV_ABORT) \ + HGOTO_ERROR(H5E_DATATYPE, H5E_CANTCONVERT, FAIL, "can't handle conversion exception") \ + /* if(except_ret==H5T_CONV_HANDLED): Fall through, user handled it */ \ + } else \ + *((DT*)D) = (DT)(*((ST*)S)); \ +} +#define H5T_CONV_us_NOEX_CORE(S,D,ST,DT,D_MIN,D_MAX,D_PREC) { \ + /* Assumes memory format of unsigned & signed integers is same */ \ + if (*((ST*)S) > (DT)(D_MAX)) { \ + *((DT*)D) = (D_MAX); \ } else \ *((DT*)D) = (DT)(*((ST*)S)); \ } -#define H5T_CONV_us(STYPE,DTYPE,ST,DT,D_MIN,D_MAX) { \ +#define H5T_CONV_us(STYPE,DTYPE,ST,DT,D_MIN,D_MAX,D_PREC) { \ assert(sizeof(ST)==sizeof(DT)); \ - H5T_CONV(H5T_CONV_us, long_long, STYPE, DTYPE, ST, DT, D_MIN, D_MAX) \ + H5T_CONV(H5T_CONV_us, long_long, STYPE, DTYPE, ST, DT, D_MIN, D_MAX, D_PREC) \ } -#define H5T_CONV_fF(STYPE,DTYPE,ST,DT,D_MIN,D_MAX) { \ +#define H5T_CONV_fF(STYPE,DTYPE,ST,DT,D_MIN,D_MAX,D_PREC) { \ assert(sizeof(ST)<=sizeof(DT)); \ - H5T_CONV(H5T_CONV_xX, long double, STYPE, DTYPE, ST, DT, D_MIN, D_MAX) \ + H5T_CONV(H5T_CONV_xX, long double, STYPE, DTYPE, ST, DT, D_MIN, D_MAX, D_PREC) \ } /* Same as H5T_CONV_Xx_CORE, except that instead of using D_MAX and D_MIN * when an overflow occurs, use the 'float' infinity values. */ -#define H5T_CONV_Ff_CORE(S,D,STYPE,DTYPE,ST,DT,D_MIN,D_MAX) { \ +#define H5T_CONV_Ff_CORE(S,D,ST,DT,D_MIN,D_MAX,D_PREC) { \ if (*((ST*)S) > (DT)(D_MAX)) { \ - if(cb_struct.func) { \ - H5T_conv_ret_t except_ret; /*callback return*/ \ - \ - except_ret = (cb_struct.func)(H5T_CONV_EXCEPT_RANGE_HI, \ - src_id, dst_id, S, D, cb_struct.user_data); \ - if(except_ret == H5T_CONV_UNHANDLED) \ - /* Let compiler convert if case is ignored by user handler*/ \ - *((DT*)D) = (H5T_NATIVE_FLOAT_POS_INF_g); \ - else if(except_ret == H5T_CONV_ABORT) \ - HGOTO_ERROR(H5E_DATATYPE, H5E_CANTCONVERT, FAIL, "can't handle conversion exception") \ - /* if(except_ret==H5T_CONV_HANDLED): Fall through, user handled it */ \ - } \ - else \ - *((DT*)D) = (H5T_NATIVE_FLOAT_POS_INF_g); \ + H5T_conv_ret_t except_ret = (cb_struct.func)(H5T_CONV_EXCEPT_RANGE_HI, \ + src_id, dst_id, S, D, cb_struct.user_data); \ + if(except_ret == H5T_CONV_UNHANDLED) \ + /* Let compiler convert if case is ignored by user handler*/ \ + *((DT*)D) = (H5T_NATIVE_FLOAT_POS_INF_g); \ + else if(except_ret == H5T_CONV_ABORT) \ + HGOTO_ERROR(H5E_DATATYPE, H5E_CANTCONVERT, FAIL, "can't handle conversion exception") \ + /* if(except_ret==H5T_CONV_HANDLED): Fall through, user handled it */ \ } else if (*((ST*)S) < (DT)(D_MIN)) { \ - if(cb_struct.func) { \ - H5T_conv_ret_t except_ret; /*callback return*/ \ - \ - except_ret = (cb_struct.func)(H5T_CONV_EXCEPT_RANGE_LOW, \ - src_id, dst_id, S, D, cb_struct.user_data); \ - if(except_ret == H5T_CONV_UNHANDLED) \ - /* Let compiler convert if case is ignored by user handler*/ \ - *((DT*)D) = (H5T_NATIVE_FLOAT_NEG_INF_g); \ - else if(except_ret == H5T_CONV_ABORT) \ - HGOTO_ERROR(H5E_DATATYPE, H5E_CANTCONVERT, FAIL, "can't handle conversion exception") \ - /* if(except_ret==H5T_CONV_HANDLED): Fall through, user handled it */ \ - } \ - else \ - *((DT*)D) = (H5T_NATIVE_FLOAT_NEG_INF_g); \ + H5T_conv_ret_t except_ret = (cb_struct.func)(H5T_CONV_EXCEPT_RANGE_LOW, \ + src_id, dst_id, S, D, cb_struct.user_data); \ + if(except_ret == H5T_CONV_UNHANDLED) \ + /* Let compiler convert if case is ignored by user handler*/ \ + *((DT*)D) = (H5T_NATIVE_FLOAT_NEG_INF_g); \ + else if(except_ret == H5T_CONV_ABORT) \ + HGOTO_ERROR(H5E_DATATYPE, H5E_CANTCONVERT, FAIL, "can't handle conversion exception") \ + /* if(except_ret==H5T_CONV_HANDLED): Fall through, user handled it */ \ + } else \ + *((DT*)D) = (DT)(*((ST*)S)); \ +} +#define H5T_CONV_Ff_NOEX_CORE(S,D,ST,DT,D_MIN,D_MAX,D_PREC) { \ + if (*((ST*)S) > (DT)(D_MAX)) { \ + *((DT*)D) = (H5T_NATIVE_FLOAT_POS_INF_g); \ + } else if (*((ST*)S) < (DT)(D_MIN)) { \ + *((DT*)D) = (H5T_NATIVE_FLOAT_NEG_INF_g); \ } else \ *((DT*)D) = (DT)(*((ST*)S)); \ } -#define H5T_CONV_Ff(STYPE,DTYPE,ST,DT,D_MIN,D_MAX) { \ +#define H5T_CONV_Ff(STYPE,DTYPE,ST,DT,D_MIN,D_MAX,D_PREC) { \ assert(sizeof(ST)>=sizeof(DT)); \ - H5T_CONV(H5T_CONV_Ff, long double, STYPE, DTYPE, ST, DT, D_MIN, D_MAX) \ + H5T_CONV(H5T_CONV_Ff, long double, STYPE, DTYPE, ST, DT, D_MIN, D_MAX, D_PREC) \ } -/* Note: this is a relative fragile hack (to use the temporary variable of the - * destination type) - it may get optimized out by the compiler. QAK - 2005/08/19 - * - * A better solution would be to find the bit position of the highest 1 bit - * in the source and the bit position of the lowest 1 bit in the source and - * determine if the number of bits between them is greater than the mantissa - * of the floating point number (including the leading "implied" 1 bit), then - * issue a precision exception. However, that's probably too slow, so we'll - * try to use this solution for now. QAK - 2005/19/08 - */ -#define H5T_CONV_xF_CORE(S,D,STYPE,DTYPE,ST,DT,D_MIN,D_MAX) { \ - DT t_s = *((ST*)S); \ - if (*((ST*)S) != (ST)t_s) { \ - if(cb_struct.func) { \ - H5T_conv_ret_t except_ret; /*callback return*/ \ +#define H5T_HI_LO_BIT_SET(TYP, V, LO, HI) { \ + unsigned count; \ + unsigned char p; \ + unsigned u; \ \ - except_ret = (cb_struct.func)(H5T_CONV_EXCEPT_PRECISION, \ + count = 0; \ + for(u = 0; u < sizeof(TYP); u++) { \ + count = ((sizeof(TYP) - 1) - u) * 8; \ + p = ((V) >> count) & 0xff; \ + if(p > 0) { \ + if(p & 0x80) \ + count += 7; \ + else if(p & 0x40) \ + count += 6; \ + else if(p & 0x20) \ + count += 5; \ + else if(p & 0x10) \ + count += 4; \ + else if(p & 0x08) \ + count += 3; \ + else if(p & 0x04) \ + count += 2; \ + else if(p & 0x02) \ + count += 1; \ + break; \ + } /* end if */ \ + } /* end for */ \ + \ + HI = count; \ + \ + count = 0; \ + for(u = 0; u < sizeof(TYP); u++) { \ + p = ((V) >> (u * 8)) & 0xff; \ + if(p > 0) { \ + count = u * 8; \ + \ + if(p & 0x01) \ + ; \ + else if(p & 0x02) \ + count += 1; \ + else if(p & 0x04) \ + count += 2; \ + else if(p & 0x08) \ + count += 3; \ + else if(p & 0x10) \ + count += 4; \ + else if(p & 0x20) \ + count += 5; \ + else if(p & 0x40) \ + count += 6; \ + else if(p & 0x80) \ + count += 7; \ + break; \ + } /* end if */ \ + } /* end for */ \ + \ + LO = count; \ +} + +#define H5T_CONV_xF_CORE(S,D,ST,DT,D_MIN,D_MAX,D_PREC) { \ + if ((sizeof(ST) * 8) > D_PREC) { \ + unsigned low_bit_pos, high_bit_pos; \ + \ + /* Detect high & low bits set in source */ \ + H5T_HI_LO_BIT_SET(ST, *((ST*)S), low_bit_pos, high_bit_pos) \ + \ + /* Check for more bits of precision in src than available in dst */ \ + if((high_bit_pos - low_bit_pos) >= D_PREC) { \ + H5T_conv_ret_t except_ret = (cb_struct.func)(H5T_CONV_EXCEPT_PRECISION, \ src_id, dst_id, S, D, cb_struct.user_data); \ if(except_ret == H5T_CONV_UNHANDLED) \ /* Let compiler convert if case is ignored by user handler*/ \ @@ -484,16 +534,19 @@ H5FL_BLK_DEFINE_STATIC(array_seq); else if(except_ret == H5T_CONV_ABORT) \ HGOTO_ERROR(H5E_DATATYPE, H5E_CANTCONVERT, FAIL, "can't handle conversion exception") \ /* if(except_ret==H5T_CONV_HANDLED): Fall through, user handled it */ \ - } \ + } \ else \ *((DT*)D) = (DT)(*((ST*)S)); \ } \ else \ *((DT*)D) = (DT)(*((ST*)S)); \ } +#define H5T_CONV_xF_NOEX_CORE(S,D,ST,DT,D_MIN,D_MAX,D_PREC) { \ + *((DT*)D) = (DT)(*((ST*)S)); \ +} -#define H5T_CONV_xF(STYPE,DTYPE,ST,DT,D_MIN,D_MAX) { \ - H5T_CONV(H5T_CONV_xF, long double, STYPE, DTYPE, ST, DT, D_MIN, D_MAX) \ +#define H5T_CONV_xF(STYPE,DTYPE,ST,DT,D_MIN,D_MAX,D_PREC) { \ + H5T_CONV(H5T_CONV_xF, long double, STYPE, DTYPE, ST, DT, D_MIN, D_MAX, D_PREC) \ } /* Added a condition branch(else if (*((ST*)S) == (DT)(D_MAX))) which seems redundant. @@ -506,71 +559,62 @@ H5FL_BLK_DEFINE_STATIC(array_seq); * Modified Ray's change to just check for the source >= the DT_MAX, so that * the exception handling routine gets called. QAK - 2005/08/08 */ -#define H5T_CONV_Fx_CORE(S,D,STYPE,DTYPE,ST,DT,D_MIN,D_MAX) { \ - if (*((ST*)S) >= (DT)(D_MAX)) { \ - if(cb_struct.func) { \ - H5T_conv_ret_t except_ret; /*callback return*/ \ - \ - except_ret = (cb_struct.func)(H5T_CONV_EXCEPT_RANGE_HI, \ - src_id, dst_id, S, D, cb_struct.user_data); \ - if(except_ret == H5T_CONV_UNHANDLED) \ - /* Let compiler convert if case is ignored by user handler*/ \ - *((DT*)D) = (D_MAX); \ - else if(except_ret == H5T_CONV_ABORT) \ - HGOTO_ERROR(H5E_DATATYPE, H5E_CANTCONVERT, FAIL, "can't handle conversion exception") \ - /* if(except_ret==H5T_CONV_HANDLED): Fall through, user handled it */ \ - } \ - else \ +#define H5T_CONV_Fx_CORE(S,D,ST,DT,D_MIN,D_MAX,D_PREC) { \ + if (*((ST*)S) >= (DT)(D_MAX)) { \ + H5T_conv_ret_t except_ret = (cb_struct.func)(H5T_CONV_EXCEPT_RANGE_HI, \ + src_id, dst_id, S, D, cb_struct.user_data); \ + if(except_ret == H5T_CONV_UNHANDLED) \ + /* Let compiler convert if case is ignored by user handler*/ \ *((DT*)D) = (D_MAX); \ + else if(except_ret == H5T_CONV_ABORT) \ + HGOTO_ERROR(H5E_DATATYPE, H5E_CANTCONVERT, FAIL, "can't handle conversion exception") \ + /* if(except_ret==H5T_CONV_HANDLED): Fall through, user handled it */ \ } else if (*((ST*)S) < (DT)(D_MIN)) { \ - if(cb_struct.func) { \ - H5T_conv_ret_t except_ret; /*callback return*/ \ - \ - except_ret = (cb_struct.func)(H5T_CONV_EXCEPT_RANGE_LOW, \ - src_id, dst_id, S, D, cb_struct.user_data); \ - if(except_ret == H5T_CONV_UNHANDLED) \ - /* Let compiler convert if case is ignored by user handler*/ \ - *((DT*)D) = (D_MIN); \ - else if(except_ret == H5T_CONV_ABORT) \ - HGOTO_ERROR(H5E_DATATYPE, H5E_CANTCONVERT, FAIL, "can't handle conversion exception") \ - /* if(except_ret==H5T_CONV_HANDLED): Fall through, user handled it */ \ - } \ - else \ + H5T_conv_ret_t except_ret = (cb_struct.func)(H5T_CONV_EXCEPT_RANGE_LOW, \ + src_id, dst_id, S, D, cb_struct.user_data); \ + if(except_ret == H5T_CONV_UNHANDLED) \ + /* Let compiler convert if case is ignored by user handler*/ \ *((DT*)D) = (D_MIN); \ + else if(except_ret == H5T_CONV_ABORT) \ + HGOTO_ERROR(H5E_DATATYPE, H5E_CANTCONVERT, FAIL, "can't handle conversion exception") \ + /* if(except_ret==H5T_CONV_HANDLED): Fall through, user handled it */ \ } else if (*((ST*)S) != (ST)((DT)(*((ST*)S)))) { \ - if(cb_struct.func) { \ - H5T_conv_ret_t except_ret; /*callback return*/ \ - \ - except_ret = (cb_struct.func)(H5T_CONV_EXCEPT_TRUNCATE, \ - src_id, dst_id, S, D, cb_struct.user_data); \ - if(except_ret == H5T_CONV_UNHANDLED) \ - /* Let compiler convert if case is ignored by user handler*/ \ - *((DT*)D) = (DT)(*((ST*)S)); \ - else if(except_ret == H5T_CONV_ABORT) \ - HGOTO_ERROR(H5E_DATATYPE, H5E_CANTCONVERT, FAIL, "can't handle conversion exception") \ - /* if(except_ret==H5T_CONV_HANDLED): Fall through, user handled it */ \ - } \ - else \ + H5T_conv_ret_t except_ret = (cb_struct.func)(H5T_CONV_EXCEPT_TRUNCATE, \ + src_id, dst_id, S, D, cb_struct.user_data); \ + if(except_ret == H5T_CONV_UNHANDLED) \ + /* Let compiler convert if case is ignored by user handler*/ \ *((DT*)D) = (DT)(*((ST*)S)); \ + else if(except_ret == H5T_CONV_ABORT) \ + HGOTO_ERROR(H5E_DATATYPE, H5E_CANTCONVERT, FAIL, "can't handle conversion exception") \ + /* if(except_ret==H5T_CONV_HANDLED): Fall through, user handled it */ \ + } \ + else \ + *((DT*)D) = (DT)(*((ST*)S)); \ +} +#define H5T_CONV_Fx_NOEX_CORE(S,D,ST,DT,D_MIN,D_MAX,D_PREC) { \ + if (*((ST*)S) >= (DT)(D_MAX)) { \ + *((DT*)D) = (D_MAX); \ + } else if (*((ST*)S) < (DT)(D_MIN)) { \ + *((DT*)D) = (D_MIN); \ } \ else \ *((DT*)D) = (DT)(*((ST*)S)); \ } -#define H5T_CONV_Fx(STYPE,DTYPE,ST,DT,D_MIN,D_MAX) { \ - H5T_CONV(H5T_CONV_Fx, long double, STYPE, DTYPE, ST, DT, D_MIN, D_MAX) \ +#define H5T_CONV_Fx(STYPE,DTYPE,ST,DT,D_MIN,D_MAX,D_PREC) { \ + H5T_CONV(H5T_CONV_Fx, long double, STYPE, DTYPE, ST, DT, D_MIN, D_MAX, D_PREC) \ } /* Since all "no exception" cores do the same thing (assign the value in the * source location to the destination location, using casting), use one "core" * to do them all. */ -#define H5T_CONV_NO_EXCEPT_CORE(S,D,STYPE,DTYPE,ST,DT,D_MIN,D_MAX) { \ +#define H5T_CONV_NO_EXCEPT_CORE(S,D,ST,DT,D_MIN,D_MAX, D_PREC) { \ *((DT*)D) = (DT)(*((ST*)S)); \ } /* The main part of every integer hardware conversion macro */ -#define H5T_CONV(GUTS,ATYPE,STYPE,DTYPE,ST,DT,D_MIN,D_MAX) { \ +#define H5T_CONV(GUTS,ATYPE,STYPE,DTYPE,ST,DT,D_MIN,D_MAX,D_PREC) { \ size_t elmtno; /*element number */ \ uint8_t *src, *s; /*source buffer */ \ uint8_t *dst, *d; /*destination buffer */ \ @@ -668,17 +712,17 @@ H5FL_BLK_DEFINE_STATIC(array_seq); if (s_mv && d_mv) { \ /* Alignment is required for both source and dest */ \ s = (uint8_t*)&aligned; \ - H5T_CONV_LOOP(PRE_SALIGN,PRE_DALIGN,POST_SALIGN,POST_DALIGN,GUTS,s,d,STYPE,DTYPE,ST,DT,D_MIN,D_MAX) \ + H5T_CONV_LOOP_OUTER(PRE_SALIGN,PRE_DALIGN,POST_SALIGN,POST_DALIGN,GUTS,s,d,ST,DT,D_MIN,D_MAX,D_PREC) \ } else if(s_mv) { \ /* Alignment is required only for source */ \ s = (uint8_t*)&aligned; \ - H5T_CONV_LOOP(PRE_SALIGN,PRE_DNOALIGN,POST_SALIGN,POST_DNOALIGN,GUTS,s,dst,STYPE,DTYPE,ST,DT,D_MIN,D_MAX) \ + H5T_CONV_LOOP_OUTER(PRE_SALIGN,PRE_DNOALIGN,POST_SALIGN,POST_DNOALIGN,GUTS,s,dst,ST,DT,D_MIN,D_MAX,D_PREC) \ } else if(d_mv) { \ /* Alignment is required only for destination */ \ - H5T_CONV_LOOP(PRE_SNOALIGN,PRE_DALIGN,POST_SNOALIGN,POST_DALIGN,GUTS,src,d,STYPE,DTYPE,ST,DT,D_MIN,D_MAX) \ + H5T_CONV_LOOP_OUTER(PRE_SNOALIGN,PRE_DALIGN,POST_SNOALIGN,POST_DALIGN,GUTS,src,d,ST,DT,D_MIN,D_MAX,D_PREC) \ } else { \ /* Alignment is not required for both source and destination */ \ - H5T_CONV_LOOP(PRE_SNOALIGN,PRE_DNOALIGN,POST_SNOALIGN,POST_DNOALIGN,GUTS,src,dst,STYPE,DTYPE,ST,DT,D_MIN,D_MAX) \ + H5T_CONV_LOOP_OUTER(PRE_SNOALIGN,PRE_DNOALIGN,POST_SNOALIGN,POST_DNOALIGN,GUTS,src,dst,ST,DT,D_MIN,D_MAX,D_PREC) \ } \ \ /* Decrement number of elements left to convert */ \ @@ -727,24 +771,33 @@ H5FL_BLK_DEFINE_STATIC(array_seq); #define H5T_CONV_LOOP_POST_DNOALIGN(DT) { \ } +/* The outer wrapper for the type conversion loop, to check for an exception handling routine */ +#define H5T_CONV_LOOP_OUTER(PRE_SALIGN_GUTS,PRE_DALIGN_GUTS,POST_SALIGN_GUTS,POST_DALIGN_GUTS,GUTS,S,D,ST,DT,D_MIN,D_MAX,D_PREC) \ + if(cb_struct.func) { \ + H5T_CONV_LOOP(PRE_SALIGN_GUTS,PRE_DALIGN_GUTS,POST_SALIGN_GUTS,POST_DALIGN_GUTS,GUTS,S,D,ST,DT,D_MIN,D_MAX,D_PREC) \ + } \ + else { \ + H5T_CONV_LOOP(PRE_SALIGN_GUTS,PRE_DALIGN_GUTS,POST_SALIGN_GUTS,POST_DALIGN_GUTS,H5_GLUE(GUTS,_NOEX),S,D,ST,DT,D_MIN,D_MAX,D_PREC) \ + } + /* The inner loop of the type conversion macro, actually converting the elements */ -#define H5T_CONV_LOOP(PRE_SALIGN_GUTS,PRE_DALIGN_GUTS,POST_SALIGN_GUTS,POST_DALIGN_GUTS,GUTS,S,D,STYPE,DTYPE,ST,DT,D_MIN,D_MAX) \ +#define H5T_CONV_LOOP(PRE_SALIGN_GUTS,PRE_DALIGN_GUTS,POST_SALIGN_GUTS,POST_DALIGN_GUTS,GUTS,S,D,ST,DT,D_MIN,D_MAX,D_PREC) \ for (elmtno=0; elmtno