summaryrefslogtreecommitdiffstats
path: root/test
diff options
context:
space:
mode:
authorQuincey Koziol <koziol@hdfgroup.org>2003-11-25 19:26:04 (GMT)
committerQuincey Koziol <koziol@hdfgroup.org>2003-11-25 19:26:04 (GMT)
commit36a46913beec7893b099466599c609007a0b108c (patch)
tree83bfece0e776c040a854cfd8de0f6d80707ef813 /test
parentd0b29413fcaab14fdb8e1a86322197fe880c4749 (diff)
downloadhdf5-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.c36
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