[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.
This commit is contained in:
Robb Matzke 1998-07-06 18:02:32 -05:00
parent 4d3351f1d7
commit cf419d05ab
7 changed files with 202 additions and 70 deletions

View File

@ -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;
}

View File

@ -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?

View File

@ -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) {

View File

@ -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;

View File

@ -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;

View File

@ -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 \

View File

@ -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
@ -673,6 +707,74 @@ test_conv_int (void)
return -1;
}
/*-------------------------------------------------------------------------
* 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
@ -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",