diff options
author | Quincey Koziol <koziol@hdfgroup.org> | 2003-11-25 19:26:04 (GMT) |
---|---|---|
committer | Quincey Koziol <koziol@hdfgroup.org> | 2003-11-25 19:26:04 (GMT) |
commit | 36a46913beec7893b099466599c609007a0b108c (patch) | |
tree | 83bfece0e776c040a854cfd8de0f6d80707ef813 /test | |
parent | d0b29413fcaab14fdb8e1a86322197fe880c4749 (diff) | |
download | hdf5-36a46913beec7893b099466599c609007a0b108c.zip hdf5-36a46913beec7893b099466599c609007a0b108c.tar.gz hdf5-36a46913beec7893b099466599c609007a0b108c.tar.bz2 |
[svn-r7883] 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)
Diffstat (limited to 'test')
-rw-r--r-- | test/dtypes.c | 36 |
1 files changed, 32 insertions, 4 deletions
diff --git a/test/dtypes.c b/test/dtypes.c index 96798e3..95f71e2 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. @@ -3944,6 +3947,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 */ @@ -4037,6 +4042,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++) { /* @@ -4217,10 +4226,29 @@ 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 |