diff options
author | Quincey Koziol <koziol@hdfgroup.org> | 2003-11-25 19:26:01 (GMT) |
---|---|---|
committer | Quincey Koziol <koziol@hdfgroup.org> | 2003-11-25 19:26:01 (GMT) |
commit | 308861617910d1b339c6d35a6d64df7789ce5237 (patch) | |
tree | d62ee628d0705a45eb123f3e25435c016ce0df5f | |
parent | 5be9d3a22c9f8a5a782ec692a6f645bf57124e61 (diff) | |
download | hdf5-308861617910d1b339c6d35a6d64df7789ce5237.zip hdf5-308861617910d1b339c6d35a6d64df7789ce5237.tar.gz hdf5-308861617910d1b339c6d35a6d64df7789ce5237.tar.bz2 |
[svn-r7882] Purpose:
Bug fix
Description:
Handle denormalized floating-point values in a more general way that
uses a different 'epsilon' for determining if two values are "close enough"
Platforms tested:
FreeBSD 4.9 (sleipnir)
h5committest
Pittsburgh Alpha Cluster (lemieux.psc.edu)
-rw-r--r-- | test/dtypes.c | 35 |
1 files changed, 31 insertions, 4 deletions
diff --git a/test/dtypes.c b/test/dtypes.c index f054002..088794f 100644 --- a/test/dtypes.c +++ b/test/dtypes.c @@ -31,6 +31,9 @@ /* Define if you want to see a count of overflows */ #undef SHOW_OVERFLOWS +/* Epsilon for floating-point comparisons */ +#define FP_EPSILON 0.000001 + /* * Offset from alinged memory returned by malloc(). This can be used to test * that type conversions handle non-aligned buffers correctly. @@ -4897,6 +4900,8 @@ test_conv_flt_1 (const char *name, hid_t src, hid_t dst) unsigned char *hw=NULL; /*ptr to hardware-conv'd*/ size_t i, j, k; /*counters */ int endian; /*machine endianess */ + size_t dst_ebias; /* Destination type's exponent bias */ + size_t dst_msize; /* Destination type's mantissa size */ #ifdef HANDLE_SIGFPE pid_t child_pid; /*process ID of child */ @@ -4990,6 +4995,10 @@ test_conv_flt_1 (const char *name, hid_t src, hid_t dst) noverflows_g = 0; #endif + /* Get "interesting" values */ + dst_ebias=H5Tget_ebias(dst); + H5Tget_fields(dst,NULL,NULL,NULL,NULL,&dst_msize); + for (i=0; i<ntests; i++) { /* @@ -5170,10 +5179,28 @@ test_conv_flt_1 (const char *name, hid_t src, hid_t dst) check_mant[1] = frexp(((long double*)hw)[0], check_expo+1); #endif } - if (check_expo[0]==check_expo[1] && - fabs(check_mant[0]-check_mant[1])<0.000001) { - continue; - } + /* Special check for denormalized values */ + if(check_expo[0]<(-(int)dst_ebias) || check_expo[1]<(-(int)dst_ebias)) { + int expo_diff=check_expo[0]-check_expo[1]; + int valid_bits=((dst_ebias+dst_msize)+MIN(check_expo[0],check_expo[1]))-1; + double epsilon=1.0; + + /* Re-scale the mantissas based on any exponent difference */ + if(expo_diff!=0) + check_mant[0] = ldexp(check_mant[0],(double)expo_diff); + + /* Compute the proper epsilon */ + epsilon=ldexp(epsilon,-valid_bits); + + /* Check for "close enough" fit with scaled epsilon value */ + if (fabs(check_mant[0]-check_mant[1])<=epsilon) + continue; + } /* end if */ + else { + if (check_expo[0]==check_expo[1] && + fabs(check_mant[0]-check_mant[1])<FP_EPSILON) + continue; + } /* end else */ } #endif |