diff options
author | Robb Matzke <matzke@llnl.gov> | 1998-07-06 23:02:32 (GMT) |
---|---|---|
committer | Robb Matzke <matzke@llnl.gov> | 1998-07-06 23:02:32 (GMT) |
commit | cf419d05ab65b423bc4ce395972e84522ca3eec5 (patch) | |
tree | 6f689a9e56f4e251f51aacec02a067b9f8d232a1 | |
parent | 4d3351f1d777bc3cb891443b6165a87251d4e643 (diff) | |
download | hdf5-cf419d05ab65b423bc4ce395972e84522ca3eec5.zip hdf5-cf419d05ab65b423bc4ce395972e84522ca3eec5.tar.gz hdf5-cf419d05ab65b423bc4ce395972e84522ca3eec5.tar.bz2 |
[svn-r454] Changes since 19980702
----------------------
./src/H5T.c
Prints statistics for no-op conversions also.
For now, hardware floating point conversions may or may not
raise SIGFPE depending on the hardware, operating system,
etc. Software conversions never raise SIGFPE and use +Inf or
-Inf for overflow.
./test/dtypes.c
Catches SIGFPE and causes the test to be skipped. Better test
for NaN.
./config/irix5.3
Removed the -U_POSIX_SOURCE because it was removed from the
main makefiles.
./bin/trace
./src/H5S.c
Fixed a typo that prevented tracing info from being added to
new API functions.
-rwxr-xr-x | bin/trace | 3 | ||||
-rw-r--r-- | config/irix5.3 | 2 | ||||
-rw-r--r-- | src/H5S.c | 2 | ||||
-rw-r--r-- | src/H5T.c | 34 | ||||
-rw-r--r-- | src/H5Tconv.c | 16 | ||||
-rw-r--r-- | test/.distdep | 4 | ||||
-rw-r--r-- | test/dtypes.c | 211 |
7 files changed, 202 insertions, 70 deletions
@@ -157,10 +157,11 @@ sub rewrite_func ($$$$$) { } } elsif ($body =~ s/((\n[ \t]*)H5TRACE\d+\s*\(.*?\);)\n/"$2$trace"/es) { # Replaced an H5TRACE macro - } elsif ($body=~s/((\n[ \t]*)FUNC_ENTER\s*\([ \t]*?\);)\n/"$1$2$trace"/es) { + } elsif ($body=~s/((\n[ \t]*)FUNC_ENTER\s*\(.*?\);)\n/"$1$2$trace"/es) { # Added an H5TRACE macro after a FUNC_ENTER macro. } else { errmesg $file, $name, "unable to insert tracing information"; + print "body=\n>>>>>", $body, "<<<<<\n"; goto error; } diff --git a/config/irix5.3 b/config/irix5.3 index c0064ef..acc375e 100644 --- a/config/irix5.3 +++ b/config/irix5.3 @@ -17,7 +17,7 @@ CC=cc RANLIB=: # What must *always* be present for things to compile correctly? -CFLAGS="$CFLAGS -U_POSIX_SOURCE -ansi -fullwarn -woff 799" +CFLAGS="$CFLAGS -ansi -fullwarn -woff 799" #CPPFLAGS="$CPPFLAGS -I." # What compiler flags should be used for code development? @@ -1026,6 +1026,7 @@ H5Sset_extent_simple (hid_t sid, int rank, const hsize_t *dims, const hsize_t *m herr_t ret_value = SUCCEED; FUNC_ENTER(H5Sset_extent_simple, FAIL); + H5TRACE4("e","iIs*h*h",sid,rank,dims,max); /* Check args */ if ((space = H5I_object(sid)) == NULL) { @@ -1336,6 +1337,7 @@ H5Screate_simple (int rank, const hsize_t *dims, const hsize_t *maxdims) int i; FUNC_ENTER(H5Screate, FAIL); + H5TRACE3("i","Is*h*h",rank,dims,maxdims); /* Check arguments */ if (rank<0) { @@ -679,6 +679,7 @@ H5T_term_interface(void) #ifdef H5T_DEBUG intn nprint=0; hsize_t nbytes; + H5T_cdata_t *cdata; #endif /* Unregister all conversion functions */ @@ -734,6 +735,39 @@ H5T_term_interface(void) H5T_path_g[i] = NULL; } +#ifdef H5T_DEBUG + /* Print debugging infor for the `noop' conversion */ + if (H5T_conv_noop==H5T_find(NULL, NULL, H5T_BKG_NO, &cdata)) { + if (cdata->stats->ncalls>0) { + if (0==nprint++) { + HDfprintf (stderr, "H5T: type conversion statistics " + "accumulated over life of library:\n"); + HDfprintf (stderr, " %-*s %8s/%-5s %8s %8s %8s %15s\n", + H5T_NAMELEN-1, "Name", "Elmts", "Calls", "User", + "System", "Elapsed", "Bandwidth"); + HDfprintf (stderr, " %-*s %8s-%-5s %8s %8s %8s %15s\n", + H5T_NAMELEN-1, "----", "-----", "-----", "----", + "------", "-------", "---------"); + } + nbytes = cdata->stats->nelmts; + HDfprintf (stderr, + " %-*s %8Hd/%-5d %8.2f %8.2f %8.2f", + H5T_NAMELEN-1, "no-op", + cdata->stats->nelmts, + cdata->stats->ncalls, + cdata->stats->timer.utime, + cdata->stats->timer.stime, + cdata->stats->timer.etime); + if (cdata->stats->timer.etime>0) { + HDfprintf (stderr, " %15g\n", + nbytes / cdata->stats->timer.etime); + } else { + HDfprintf (stderr, " %15s\n", "Inf"); + } + } + } +#endif + /* Clear conversion tables */ H5T_apath_g = 0; H5T_npath_g = 0; diff --git a/src/H5Tconv.c b/src/H5Tconv.c index 800a9ea..930b330 100644 --- a/src/H5Tconv.c +++ b/src/H5Tconv.c @@ -13,7 +13,6 @@ #include <H5Eprivate.h> #include <H5MMprivate.h> #include <H5Tpkg.h> -#include <float.h> /*for FLT_MAX and FLT_MIN */ #include <math.h> /*for ceil() */ /* Conversion data for H5T_conv_struct() */ @@ -1350,19 +1349,8 @@ H5T_conv_double_float (hid_t __unused__ src_id, hid_t __unused__ dst_id, s = (double*)buf; d = (float*)buf; - /* - * We have to watch out because some machines generate a SIGFPE if - * the source has a larger magnitude than can be represented in the - * destination. - */ - for (elmtno=0; elmtno<nelmts; elmtno++, d++, s++) { - if (*s > FLT_MAX) { - *d = FLT_MAX; - } else if (*s < -FLT_MAX) { - *d = -FLT_MAX; - } else { - *d = *s; - } + for (elmtno=0; elmtno<nelmts; elmtno++) { + *d++ = *s++; } break; diff --git a/test/.distdep b/test/.distdep index a2fcc62..5706161 100644 --- a/test/.distdep +++ b/test/.distdep @@ -182,7 +182,9 @@ dtypes.o: \ ../src/H5Tpkg.h \ ../src/H5HGprivate.h \ ../src/H5Fprivate.h \ - ../src/H5private.h + ../src/H5private.h \ + ../src/H5Tprivate.h \ + ../src/H5Gprivate.h hyperslab.o: \ hyperslab.c \ ../src/H5private.h \ diff --git a/test/dtypes.c b/test/dtypes.c index 2cab029..e9e8f06 100644 --- a/test/dtypes.c +++ b/test/dtypes.c @@ -8,12 +8,13 @@ * Purpose: Tests the data type interface (H5T) */ #include <assert.h> -#include <float.h> #include <hdf5.h> #include <math.h> #include <signal.h> #include <stdio.h> #include <stdlib.h> +#include <sys/types.h> +#include <sys/wait.h> #include <unistd.h> #define H5T_PACKAGE @@ -52,6 +53,39 @@ typedef enum flt_t { FLT_FLOAT, FLT_DOUBLE, FLT_LDOUBLE, FLT_OTHER } flt_t; +/* + * Some machines generate SIGFPE on floating point overflows. According to + * the Posix standard, we cannot assume that we can continue from such a + * signal. Therefore, if the following constant is defined then tests that + * might raise SIGFPE are executed in a child process. + */ +#define HANDLE_SIGFPE + + +/*------------------------------------------------------------------------- + * Function: fpe_handler + * + * Purpose: Exit with 255 + * + * Return: void + * + * Programmer: Robb Matzke + * Monday, July 6, 1998 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +#ifdef HANDLE_SIGFPE +static void +fpe_handler(int __unused__ signo) +{ + puts(" -SKIP-"); + puts(" Test skipped due to SIGFPE from probable overflow."); + exit(255); +} +#endif + /*------------------------------------------------------------------------- * Function: cleanup @@ -675,6 +709,74 @@ test_conv_int (void) /*------------------------------------------------------------------------- + * Function: my_isnan + * + * Purpose: Determines whether VAL points to NaN. + * + * Return: TRUE or FALSE + * + * Programmer: Robb Matzke + * Monday, July 6, 1998 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +static int +my_isnan(flt_t type, void *val) +{ + int retval; + char s[256]; + + switch (type) { + case FLT_FLOAT: + retval = (*((float*)val)!=*((float*)val)); + break; + + case FLT_DOUBLE: + retval = (*((double*)val)!=*((double*)val)); + break; + + case FLT_LDOUBLE: + retval = (*((long double*)val)!=*((long double*)val)); + break; + + default: + return 0; + } + + /* + * Sometimes NaN==NaN (e.g., DEC Alpha) so we try to print it and see if + * the result contains a NaN string. + */ + if (!retval) { + switch (type) { + case FLT_FLOAT: + sprintf(s, "%g", *((float*)val)); + break; + + case FLT_DOUBLE: + sprintf(s, "%g", *((double*)val)); + break; + + case FLT_LDOUBLE: + sprintf(s, "%Lg", *((long double*)val)); + break; + + default: + return 0; + } + + if (!strstr(s, "NaN") || !strstr(s, "NAN") || !strstr(s, "nan")) { + retval = 1; + } + } + + return retval; +} + + +/*------------------------------------------------------------------------- * Function: test_conv_flt_1 * * Purpose: Test conversion of random floating point values from SRC to @@ -714,6 +816,39 @@ test_conv_flt_1 (const char *name, hid_t src, hid_t dst) size_t i, j, k; /*counters */ int endian; /*machine endianess */ +#ifdef HANDLE_SIGFPE + pid_t child_pid; /*process ID of child */ + int status; /*child exit status */ + + /* + * Some systems generage SIGFPE during floating point overflow and we + * cannot assume that we can continue from such a signal. Therefore, we + * fork here and let the child run the test and return the number of + * failures with the exit status. + */ + fflush(stdout); + fflush(stderr); + if ((child_pid=fork())<0) { + perror("fork"); + return 1; + } else if (child_pid>0) { + while (child_pid!=waitpid(child_pid, &status, 0)) /*void*/; + if (WIFEXITED(status) && 255==WEXITSTATUS(status)) { + return 0; /*child exit after catching SIGFPE*/ + } else if (WIFEXITED(status)) { + return WEXITSTATUS(status); + } else { + puts(" Child didn't exit normally."); + return 1; + } + } + + /* + * The remainder of this function is executed only by the child. + */ + signal(SIGFPE,fpe_handler); +#endif + /* What are the names of the source and destination types */ if (H5Tequal(src, H5T_NATIVE_FLOAT)) { src_type_name = "float"; @@ -785,6 +920,9 @@ 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++) { + hw_f = 911.0; + hw_d = 911.0; + hw_ld = 911.0; /* The hardware conversion */ if (FLT_FLOAT==src_type) { @@ -800,14 +938,7 @@ test_conv_flt_1 (const char *name, hid_t src, hid_t dst) } } else if (FLT_DOUBLE==src_type) { if (FLT_FLOAT==dst_type) { - /* Watch out for that FPE on overflow! */ - if (((double*)saved)[j] > FLT_MAX) { - hw_f = FLT_MAX; - } else if (((double*)saved)[j] < -FLT_MAX) { - hw_f = -FLT_MAX; - } else { - hw_f = ((double*)saved)[j]; - } + hw_f = ((double*)saved)[j]; hw = (unsigned char*)&hw_f; } else if (FLT_DOUBLE==dst_type) { hw_d = ((double*)saved)[j]; @@ -818,24 +949,10 @@ test_conv_flt_1 (const char *name, hid_t src, hid_t dst) } } else { if (FLT_FLOAT==dst_type) { - /* Watch out for that FPE on overflow! */ - if (((long double*)saved)[j] > FLT_MAX) { - hw_f = FLT_MAX; - } else if (((long double*)saved)[j] < -FLT_MAX) { - hw_f = -FLT_MAX; - } else { - hw_f = ((long double*)saved)[j]; - } + hw_f = ((long double*)saved)[j]; hw = (unsigned char*)&hw_f; } else if (FLT_DOUBLE==dst_type) { - /* Watch out for that FPE! */ - if (((long double*)saved)[j] > DBL_MAX) { - hw_d = DBL_MAX; - } else if (((long double*)saved)[j] < -DBL_MAX) { - hw_d = -DBL_MAX; - } else { - hw_d = ((long double*)saved)[j]; - } + hw_d = ((long double*)saved)[j]; hw = (unsigned char*)&hw_d; } else { hw_ld = ((long double*)saved)[j]; @@ -857,16 +974,16 @@ test_conv_flt_1 (const char *name, hid_t src, hid_t dst) * pattern for NaN by setting the significand to all ones. */ if (FLT_FLOAT==dst_type && - ((float*)buf)[j]!=((float*)buf)[j] && - ((float*)hw)[0]!=((float*)hw)[0]) { + my_isnan(dst_type, (float*)buf+j) && + my_isnan(dst_type, hw)) { continue; } else if (FLT_DOUBLE==dst_type && - ((double*)buf)[j]!=((double*)buf)[j] && - ((double*)hw)[0]!=((double*)hw)[0]) { + my_isnan(dst_type, (double*)buf+j) && + my_isnan(dst_type, hw)) { continue; } else if (FLT_LDOUBLE==dst_type && - ((long double*)buf)[j]!=((long double*)buf)[j] && - ((long double*)hw)[0]!=((long double*)hw)[0]) { + my_isnan(dst_type, (long double*)buf+j) && + my_isnan(dst_type, hw)) { continue; } #endif @@ -877,16 +994,7 @@ test_conv_flt_1 (const char *name, hid_t src, hid_t dst) * hardware conversions on some machines return NaN instead of * overflowing to +Inf or -Inf or underflowing to +0 or -0. */ - if (FLT_FLOAT==dst_type && - *((float*)hw)!=*((float*)hw)) { - continue; - } else if (FLT_DOUBLE==dst_type && - *((double*)hw)!=*((double*)hw)) { - continue; - } else if (FLT_LDOUBLE==dst_type && - *((long double*)hw)!=*((long double*)hw)) { - continue; - } + if (my_isnan(dst_type, hw)) continue; #endif #if 1 @@ -970,12 +1078,20 @@ test_conv_flt_1 (const char *name, hid_t src, hid_t dst) done: if (buf) free (buf); if (saved) free (saved); +#ifdef HANDLE_SIGFPE + exit(MIN((int)fails_all_tests, 254)); +#else return (int)fails_all_tests; +#endif error: if (buf) free (buf); if (saved) free (saved); - return (int)MIN(1, fails_all_tests); +#ifdef HANDLE_SIGFPE + exit(MIN(MAX((int)fails_all_tests, 1), 254)); +#else + return MAX((int)fails_all_tests, 1); +#endif } @@ -1000,10 +1116,6 @@ main(void) { unsigned long nerrors = 0; -#if 0 - signal(SIGFPE,SIG_IGN); -#endif - /* Set the error handler */ H5Eset_auto (display_error_cb, NULL); @@ -1015,12 +1127,6 @@ main(void) nerrors += test_named ()<0 ? 1 : 0; nerrors += test_conv_int ()<0 ? 1 : 0; -#ifndef LATER - /* - * NOT READY FOR TESTING YET BECAUSE SOME SYSTEMS GENERATE A SIGFPE WHEN - * AN OVERFLOW OCCURS CASTING A DOUBLE TO A FLOAT. - */ -#else /* Test degenerate cases */ nerrors += test_conv_flt_1("noop", H5T_NATIVE_FLOAT, H5T_NATIVE_FLOAT); nerrors += test_conv_flt_1("noop", H5T_NATIVE_DOUBLE, H5T_NATIVE_DOUBLE); @@ -1038,7 +1144,6 @@ main(void) nerrors += test_conv_flt_1("sw", H5T_NATIVE_DOUBLE, H5T_NATIVE_LDOUBLE); nerrors += test_conv_flt_1("sw", H5T_NATIVE_LDOUBLE, H5T_NATIVE_FLOAT); nerrors += test_conv_flt_1("sw", H5T_NATIVE_LDOUBLE, H5T_NATIVE_DOUBLE); -#endif if (nerrors) { printf("***** %lu FAILURE%s! *****\n", |