From cf419d05ab65b423bc4ce395972e84522ca3eec5 Mon Sep 17 00:00:00 2001 From: Robb Matzke Date: Mon, 6 Jul 1998 18:02:32 -0500 Subject: [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. --- bin/trace | 3 +- config/irix5.3 | 2 +- src/H5S.c | 2 + src/H5T.c | 34 ++++++++++ src/H5Tconv.c | 16 +---- test/.distdep | 4 +- test/dtypes.c | 211 ++++++++++++++++++++++++++++++++++++++++++--------------- 7 files changed, 202 insertions(+), 70 deletions(-) diff --git a/bin/trace b/bin/trace index a124d5c..f190857 100755 --- a/bin/trace +++ b/bin/trace @@ -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? diff --git a/src/H5S.c b/src/H5S.c index ad4cb1a..7ebf490 100644 --- a/src/H5S.c +++ b/src/H5S.c @@ -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) { diff --git a/src/H5T.c b/src/H5T.c index 4fe6078..8026516 100644 --- a/src/H5T.c +++ b/src/H5T.c @@ -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 #include #include -#include /*for FLT_MAX and FLT_MIN */ #include /*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 FLT_MAX) { - *d = FLT_MAX; - } else if (*s < -FLT_MAX) { - *d = -FLT_MAX; - } else { - *d = *s; - } + for (elmtno=0; elmtno -#include #include #include #include #include #include +#include +#include #include #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 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", -- cgit v0.12