summaryrefslogtreecommitdiffstats
path: root/test
diff options
context:
space:
mode:
Diffstat (limited to 'test')
-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);