diff options
Diffstat (limited to 'test')
-rw-r--r-- | test/dtypes.c | 28 |
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); |