summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorQuincey Koziol <koziol@hdfgroup.org>2003-11-25 19:26:01 (GMT)
committerQuincey Koziol <koziol@hdfgroup.org>2003-11-25 19:26:01 (GMT)
commit308861617910d1b339c6d35a6d64df7789ce5237 (patch)
treed62ee628d0705a45eb123f3e25435c016ce0df5f
parent5be9d3a22c9f8a5a782ec692a6f645bf57124e61 (diff)
downloadhdf5-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.c35
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