summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAlbert Cheng <acheng@hdfgroup.org>2004-04-16 21:26:37 (GMT)
committerAlbert Cheng <acheng@hdfgroup.org>2004-04-16 21:26:37 (GMT)
commit7f2eb1127ab1a9c503f5cb65b7453c3c819b76a3 (patch)
treec00330e0ce715e887a54bd4e565d02a723e4af2f
parent84960eed3cf0f418da4a5e0cdca31eee76110b29 (diff)
downloadhdf5-7f2eb1127ab1a9c503f5cb65b7453c3c819b76a3.zip
hdf5-7f2eb1127ab1a9c503f5cb65b7453c3c819b76a3.tar.gz
hdf5-7f2eb1127ab1a9c503f5cb65b7453c3c819b76a3.tar.bz2
[svn-r8360] Purpose:
bug fix. Description: On LANL QSC, test/dtypes "sw long double -> double" had failed when the long double values were too small, smaller than the minimum double normalized floating number. The hw in QSC converts them mostly to 0 but occasionally, it converts to the some non-zero values which are still <= the minimum double normalized number. But the conversion verification did not like them and flagged them as errors. Solution: Added code to check if the src value is already smaller than the minimum number the float class can hold. When that happens and if both hw and sw conversion results are <= the minimum number, then accepts them as okay because if the src is smaller than the dst minimum number, an underflow has occured. Platforms tested: Tested in LANL QSC and Theta.
-rw-r--r--test/dtypes.c28
1 files changed, 28 insertions, 0 deletions
diff --git a/test/dtypes.c b/test/dtypes.c
index 5193115..b9af7d6 100644
--- a/test/dtypes.c
+++ b/test/dtypes.c
@@ -4755,6 +4755,11 @@ my_isnan(dtype_t type, void *val)
* Tuesday, June 23, 1998
*
* Modifications:
+ * Albert Cheng, Apr 16, 2004
+ * Check for underflow condition. If the src number is
+ * smaller than the dst MIN float number, consider it okay
+ * if the converted sw and hw dst are both less than or
+ * equal to the dst MIN float number.
*
*-------------------------------------------------------------------------
*/
@@ -4780,6 +4785,8 @@ test_conv_flt_1 (const char *name, hid_t src, hid_t dst)
long double hw_ld; /*hardware-converted */
#endif
unsigned char *hw=NULL; /*ptr to hardware-conv'd*/
+ int underflow; /*underflow occurred */
+ int uflow=0; /*underflow debug counters*/
size_t i, j, k; /*counters */
int endian; /*machine endianess */
size_t src_ebias; /* Source type's exponent bias */
@@ -4949,6 +4956,7 @@ test_conv_flt_1 (const char *name, hid_t src, hid_t dst)
/* Check the software results against the hardware */
for (j=0; j<nelmts; j++) {
+ underflow = 0;
hw_f = 911.0;
hw_d = 911.0;
#if H5_SIZEOF_LONG_DOUBLE!=H5_SIZEOF_DOUBLE
@@ -4956,6 +4964,7 @@ test_conv_flt_1 (const char *name, hid_t src, hid_t dst)
#endif
/* The hardware conversion */
+ /* Check for underflow when src is a "larger" float than dst.*/
if (FLT_FLOAT==src_type) {
HDmemcpy(aligned, saved+j*sizeof(float), sizeof(float));
if (FLT_FLOAT==dst_type) {
@@ -4975,6 +4984,7 @@ test_conv_flt_1 (const char *name, hid_t src, hid_t dst)
if (FLT_FLOAT==dst_type) {
hw_f = (float)(*((double*)aligned));
hw = (unsigned char*)&hw_f;
+ underflow = fabs(*((double*)aligned)) < FLT_MIN;
} else if (FLT_DOUBLE==dst_type) {
hw_d = *((double*)aligned);
hw = (unsigned char*)&hw_d;
@@ -4990,15 +5000,20 @@ test_conv_flt_1 (const char *name, hid_t src, hid_t dst)
if (FLT_FLOAT==dst_type) {
hw_f = *((long double*)aligned);
hw = (unsigned char*)&hw_f;
+ underflow = fabsl(*((long double*)aligned)) < FLT_MIN;
} else if (FLT_DOUBLE==dst_type) {
hw_d = *((long double*)aligned);
hw = (unsigned char*)&hw_d;
+ underflow = fabsl(*((long double*)aligned)) < DBL_MIN;
} else {
hw_ld = *((long double*)aligned);
hw = (unsigned char*)&hw_ld;
}
#endif
}
+ if (underflow){
+ uflow++;
+ }
/* Are the two results the same? */
for (k=0; k<dst_size; k++)
@@ -5042,6 +5057,9 @@ test_conv_flt_1 (const char *name, hid_t src, hid_t dst)
* exponents are the same and the mantissa is the same to a
* certain precision. This is needed on machines that don't
* round as expected.
+ * If the src number is smaller than the dst MIN float number,
+ * consider it okay if the converted sw and hw dst are both
+ * less than or equal to the dst MIN float number.
*/
{
double check_mant[2];
@@ -5050,17 +5068,24 @@ test_conv_flt_1 (const char *name, hid_t src, hid_t dst)
if (FLT_FLOAT==dst_type) {
float x;
HDmemcpy(&x, &buf[j*dst_size], sizeof(float));
+ if (underflow &&
+ fabsf(x) <= FLT_MIN && fabsf(hw_f) <= FLT_MIN)
+ continue; /* all underflowed, no error */
check_mant[0] = HDfrexpf(x, check_expo+0);
check_mant[1] = HDfrexpf(hw_f, check_expo+1);
} else if (FLT_DOUBLE==dst_type) {
double x;
HDmemcpy(&x, &buf[j*dst_size], sizeof(double));
+ if (underflow &&
+ fabs(x) <= DBL_MIN && fabs(hw_d) <= DBL_MIN)
+ continue; /* all underflowed, no error */
check_mant[0] = HDfrexp(x, check_expo+0);
check_mant[1] = HDfrexp(hw_d, check_expo+1);
#if H5_SIZEOF_LONG_DOUBLE!=H5_SIZEOF_DOUBLE
} else {
long double x;
HDmemcpy(&x, &buf[j*dst_size], sizeof(long double));
+ /* dst is largest float, no need to check underflow. */
check_mant[0] = HDfrexpl(x, check_expo+0);
check_mant[1] = HDfrexpl(hw_ld, check_expo+1);
#endif
@@ -5193,6 +5218,9 @@ test_conv_flt_1 (const char *name, hid_t src, hid_t dst)
#endif
done:
+#ifdef AKCDEBUG
+ printf("uflow=%d, fails_all_tests=%d\n", uflow, fails_all_tests);
+#endif
if (buf) aligned_free(buf);
if (saved) aligned_free(saved);
if (aligned) HDfree(aligned);