summaryrefslogtreecommitdiffstats
path: root/src/H5Tconv.c
diff options
context:
space:
mode:
authorQuincey Koziol <koziol@hdfgroup.org>2003-11-24 16:47:18 (GMT)
committerQuincey Koziol <koziol@hdfgroup.org>2003-11-24 16:47:18 (GMT)
commit6d8dd9c50412803fd3cc3af18c4e618c3b97cec3 (patch)
treee23e841019af738a69c2bf5633bd3a671dd4e3fb /src/H5Tconv.c
parent2106568c9cf25cc350e688276268465366a50d8f (diff)
downloadhdf5-6d8dd9c50412803fd3cc3af18c4e618c3b97cec3.zip
hdf5-6d8dd9c50412803fd3cc3af18c4e618c3b97cec3.tar.gz
hdf5-6d8dd9c50412803fd3cc3af18c4e618c3b97cec3.tar.bz2
[svn-r7875] Purpose:
Omnibus floating-point bug fix changes Description: There are a number of problems in the floating-point conversion code that were exposed by Ray's recent int<->float checkin: - The 'my_isnan' code in test/dtypes.c was broken and would always return true. The meant that the actual values in the float<->float conversion tests were _never_ checked, hiding the other bugs included in this checkin. - A recent change I made to the type conversion code used "FLT_MIN" instead of "-FLT_MAX" for the most negative 'float' value for the double->float conversion, which meant that any the negative number that was converted from a double to a float would have been mapped to zero, essentially. - A change that Robb appeared to have made ~2.5 years ago to the "generic" float->float conversion routine appears to be incorrect and I've backed it out. - Floating-point conversions on SGI's which converted denormalized values would be mapped to zero instead of being propertly preserved in the new type. This was addressed by an SGI-specific system call to prevent the behavior. Solution: Described above, generally. Platforms tested: FreeBSD 4.9 (sleipnir) h5committest Misc. update: release_docs/RELEASE update forthcoming...
Diffstat (limited to 'src/H5Tconv.c')
-rw-r--r--src/H5Tconv.c21
1 files changed, 19 insertions, 2 deletions
diff --git a/src/H5Tconv.c b/src/H5Tconv.c
index 8e40b0a..53f0b29 100644
--- a/src/H5Tconv.c
+++ b/src/H5Tconv.c
@@ -307,9 +307,23 @@ H5FL_BLK_DEFINE_STATIC(array_seq);
H5T_CONV(H5T_CONV_xX, double, STYPE, DTYPE, ST, DT, D_MIN, D_MAX) \
}
+/* 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) { \
+ if (*((ST*)S) > (DT)(D_MAX)) { \
+ if (!H5T_overflow_g || (H5T_overflow_g)(src_id, dst_id, S, D)<0) \
+ *((DT*)D) = (H5T_NATIVE_FLOAT_POS_INF_g); \
+ } else if (*((ST*)S) < (D_MIN)) { \
+ if (!H5T_overflow_g || (H5T_overflow_g)(src_id, dst_id, S, D)<0) \
+ *((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) { \
assert(sizeof(ST)>=sizeof(DT)); \
- H5T_CONV(H5T_CONV_Xx, double, STYPE, DTYPE, ST, DT, D_MIN, D_MAX) \
+ H5T_CONV(H5T_CONV_Ff, double, STYPE, DTYPE, ST, DT, D_MIN, D_MAX) \
}
#define H5T_CONV_xF(STYPE,DTYPE,ST,DT,D_MIN,D_MAX) { \
@@ -3351,6 +3365,8 @@ H5T_conv_f_f (hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata, hsize_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) {
@@ -3379,6 +3395,7 @@ H5T_conv_f_f (hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata, hsize_t nelmts,
H5T_bit_set(d, dst.u.f.mpos, dst.u.f.msize, FALSE);
}
}
+#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);
@@ -6674,7 +6691,7 @@ H5T_conv_double_float (hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata,
FUNC_ENTER_NOAPI(H5T_conv_float_double, FAIL);
- H5T_CONV_Ff(DOUBLE, FLOAT, double, float, FLT_MIN, FLT_MAX);
+ H5T_CONV_Ff(DOUBLE, FLOAT, double, float, -FLT_MAX, FLT_MAX);
done:
FUNC_LEAVE_NOAPI(ret_value);