From 54540e224d9fa0689dfe1d839fe115c2e7bf3a79 Mon Sep 17 00:00:00 2001 From: Raymond Lu Date: Fri, 21 Nov 2003 12:07:44 -0500 Subject: [svn-r7869] *** empty log message *** --- test/Makefile.in | 2 +- test/dtypes.c | 1476 +++++++++++++++++++++++++++++++++++++++++++++++------- 2 files changed, 1295 insertions(+), 183 deletions(-) diff --git a/test/Makefile.in b/test/Makefile.in index 823c088..7a96a15 100644 --- a/test/Makefile.in +++ b/test/Makefile.in @@ -228,5 +228,5 @@ error_test: error_test.lo err_compat: err_compat.lo @$(LT_LINK_EXE) $(CFLAGS) -o $@ err_compat.lo $(LIB) $(LIBHDF5) $(LDFLAGS) $(LIBS) - + @CONCLUDE@ diff --git a/test/dtypes.c b/test/dtypes.c index 2c13b3d..3dc06ba 100644 --- a/test/dtypes.c +++ b/test/dtypes.c @@ -71,15 +71,11 @@ typedef struct complex_t { */ #define ENDIAN(Z,I) (H5T_ORDER_BE==endian?(I):(Z)-((I)+1)) - -typedef enum flt_t { - FLT_FLOAT, FLT_DOUBLE, FLT_LDOUBLE, FLT_OTHER -} flt_t; - -typedef enum int_t { +typedef enum dtype_t { INT_CHAR, INT_UCHAR, INT_SHORT, INT_USHORT, INT_INT, INT_UINT, - INT_LONG, INT_ULONG, INT_LLONG, INT_ULLONG, INT_OTHER -} int_t; + INT_LONG, INT_ULONG, INT_LLONG, INT_ULLONG, FLT_FLOAT, FLT_DOUBLE, + FLT_LDOUBLE, OTHER +} dtype_t; /* Count the number of overflows */ #ifdef SHOW_OVERFLOWS @@ -111,6 +107,8 @@ static int num_opaque_conversions_g = 0; #define aligned_free(M) free((char*)(M)-ALIGNMENT) void some_dummy_func(float x); +hbool_t overflows(unsigned char *origin_bits, dtype_t src_dtype, + size_t src_size_bytes, size_t dst_num_bits); /*------------------------------------------------------------------------- @@ -2779,7 +2777,7 @@ test_conv_int_1(const char *name, hid_t src, hid_t dst) size_t fails_all_tests=0; /*number of failures */ size_t fails_this_test; /*fails for this test */ char str[256]; /*hello string */ - int_t src_type, dst_type; /*data types */ + dtype_t src_type, dst_type; /*data types */ const char *src_type_name=NULL; /*source type name */ const char *dst_type_name=NULL; /*destination type name */ int endian; /*machine endianess */ @@ -2839,7 +2837,7 @@ test_conv_int_1(const char *name, hid_t src, hid_t dst) src_type = INT_ULLONG; } else { src_type_name = "UNKNOWN"; - src_type = INT_OTHER; + src_type = OTHER; } if (H5Tequal(dst, H5T_NATIVE_SCHAR)) { @@ -2874,11 +2872,11 @@ test_conv_int_1(const char *name, hid_t src, hid_t dst) dst_type = INT_ULLONG; } else { dst_type_name = "UNKNOWN"; - dst_type = INT_OTHER; + dst_type = OTHER; } /* Sanity checks */ - if (INT_OTHER==src_type || INT_OTHER==dst_type) { + if (OTHER==src_type || OTHER==dst_type) { sprintf(str, "Testing random %s %s -> %s conversions", name, src_type_name, dst_type_name); printf("%-70s", str); @@ -2973,7 +2971,10 @@ test_conv_int_1(const char *name, hid_t src, hid_t dst) sizeof(unsigned long_long)); hw_char = (char)(*((unsigned long_long*)aligned)); break; - case INT_OTHER: + case FLT_FLOAT: + case FLT_DOUBLE: + case FLT_LDOUBLE: + case OTHER: break; } } else if (INT_UCHAR==dst_type) { @@ -3027,7 +3028,10 @@ test_conv_int_1(const char *name, hid_t src, hid_t dst) hw_uchar = (unsigned char)(*((unsigned long_long*) aligned)); break; - case INT_OTHER: + case FLT_FLOAT: + case FLT_DOUBLE: + case FLT_LDOUBLE: + case OTHER: break; } } else if (INT_SHORT==dst_type) { @@ -3079,7 +3083,11 @@ test_conv_int_1(const char *name, hid_t src, hid_t dst) sizeof(unsigned long_long)); hw_short = (short)(*((unsigned long_long*)aligned)); break; - case INT_OTHER: + + case FLT_FLOAT: + case FLT_DOUBLE: + case FLT_LDOUBLE: + case OTHER: break; } } else if (INT_USHORT==dst_type) { @@ -3132,7 +3140,10 @@ test_conv_int_1(const char *name, hid_t src, hid_t dst) hw_ushort = (unsigned short)(*((unsigned long_long*) aligned)); break; - case INT_OTHER: + case FLT_FLOAT: + case FLT_DOUBLE: + case FLT_LDOUBLE: + case OTHER: break; } } else if (INT_INT==dst_type) { @@ -3184,7 +3195,10 @@ test_conv_int_1(const char *name, hid_t src, hid_t dst) sizeof(unsigned long_long)); hw_int = (int)(*((unsigned long_long*)aligned)); break; - case INT_OTHER: + case FLT_FLOAT: + case FLT_DOUBLE: + case FLT_LDOUBLE: + case OTHER: break; } } else if (INT_UINT==dst_type) { @@ -3237,7 +3251,10 @@ test_conv_int_1(const char *name, hid_t src, hid_t dst) sizeof(unsigned long_long)); hw_uint = (unsigned int)(*((unsigned long_long*)aligned)); break; - case INT_OTHER: + case FLT_FLOAT: + case FLT_DOUBLE: + case FLT_LDOUBLE: + case OTHER: break; } } else if (INT_LONG==dst_type) { @@ -3290,7 +3307,10 @@ test_conv_int_1(const char *name, hid_t src, hid_t dst) sizeof(unsigned long_long)); hw_long = (long int)(*((unsigned long_long*)aligned)); break; - case INT_OTHER: + case FLT_FLOAT: + case FLT_DOUBLE: + case FLT_LDOUBLE: + case OTHER: break; } } else if (INT_ULONG==dst_type) { @@ -3344,7 +3364,10 @@ test_conv_int_1(const char *name, hid_t src, hid_t dst) hw_ulong = (unsigned long)(*((unsigned long_long*) aligned)); break; - case INT_OTHER: + case FLT_FLOAT: + case FLT_DOUBLE: + case FLT_LDOUBLE: + case OTHER: break; } } else if (INT_LLONG==dst_type) { @@ -3397,7 +3420,10 @@ test_conv_int_1(const char *name, hid_t src, hid_t dst) sizeof(unsigned long_long)); hw_llong = (long_long)(*((unsigned long_long*)aligned)); break; - case INT_OTHER: + case FLT_FLOAT: + case FLT_DOUBLE: + case FLT_LDOUBLE: + case OTHER: break; } } else if (INT_ULLONG==dst_type) { @@ -3455,7 +3481,10 @@ test_conv_int_1(const char *name, hid_t src, hid_t dst) hw_ullong = (unsigned long_long)(*((unsigned long_long*) aligned)); break; - case INT_OTHER: + case FLT_FLOAT: + case FLT_DOUBLE: + case FLT_LDOUBLE: + case OTHER: break; } } @@ -3651,7 +3680,7 @@ test_conv_int_1(const char *name, hid_t src, hid_t dst) HDfprintf(stdout," %29"H5_PRINTF_LL_WIDTH"u\n", *((unsigned long_long*)aligned)); break; - case INT_OTHER: + case OTHER: break; } @@ -3704,7 +3733,7 @@ test_conv_int_1(const char *name, hid_t src, hid_t dst) HDfprintf(stdout," %29"H5_PRINTF_LL_WIDTH"u\n", *((unsigned long_long*)aligned)); break; - case INT_OTHER: + case OTHER: break; } @@ -3745,7 +3774,7 @@ test_conv_int_1(const char *name, hid_t src, hid_t dst) case INT_ULLONG: HDfprintf(stdout," %29"H5_PRINTF_LL_WIDTH"u\n", *((unsigned long_long*)hw)); break; - case INT_OTHER: + case OTHER: break; } @@ -3835,155 +3864,98 @@ test_conv_int_2(void) /*------------------------------------------------------------------------- - * Function: my_isnan - * - * Purpose: Determines whether VAL points to NaN. - * - * Return: TRUE or FALSE + * Function: test_conv_int_float * - * Programmer: Robb Matzke - * Monday, July 6, 1998 - * - * Modifications: - * - *------------------------------------------------------------------------- - */ -static int -my_isnan(flt_t type, void *val) -{ - int retval; - char s[256]; - - if (FLT_FLOAT==type) { - float x; - memcpy(&x, val, sizeof(float)); - retval = (x!=x); - } else if (FLT_DOUBLE==type) { - double x; - memcpy(&x, val, sizeof(double)); - retval = (x!=x); -#if H5_SIZEOF_LONG_DOUBLE!=H5_SIZEOF_DOUBLE - } else if (FLT_LDOUBLE==type) { - long double x; - memcpy(&x, val, sizeof(long double)); - retval = (x!=x); -#endif - } else { - 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) { - if (FLT_FLOAT==type) { - float x; - memcpy(&x, val, sizeof(float)); - sprintf(s, "%g", x); - } else if (FLT_DOUBLE==type) { - double x; - memcpy(&x, val, sizeof(double)); - sprintf(s, "%g", x); -#if H5_SIZEOF_LONG_DOUBLE!=H5_SIZEOF_DOUBLE - } else if (FLT_LDOUBLE==type) { - long double x; - memcpy(&x, val, sizeof(long double)); - sprintf(s, "%Lg", x); -#endif - } else { - return 0; - } - if (!strstr(s, "NaN") || !strstr(s, "NAN") || !strstr(s, "nan")) { - retval = 1; - } - } - - return retval; -} - - -/*------------------------------------------------------------------------- - * Function: test_conv_flt_1 + * Purpose: Test conversion between random integer and float values + * from SRC to DST. These types should be any combination of: * - * Purpose: Test conversion of random floating point values from SRC to - * DST. These types should be H5T_NATIVE_FLOAT, - * H5T_NATIVE_DOUBLE, or H5T_NATIVE_LDOUBLE. + * H5T_NATIVE_SCHAR H5T_NATIVE_FLOAT + * H5T_NATIVE_SHORT H5T_NATIVE_DOUBLE + * H5T_NATIVE_INT H5T_NATIVE_LDOUBLE + * H5T_NATIVE_LONG + * H5T_NATIVE_LLONG * * Return: Success: 0 * * Failure: number of errors * - * Programmer: Robb Matzke - * Tuesday, June 23, 1998 + * Programmer: Raymond Lu + * Thursday, November 6, 2003 * * Modifications: * *------------------------------------------------------------------------- */ static int -test_conv_flt_1 (const char *name, hid_t src, hid_t dst) +test_conv_int_float(const char *name, hid_t src, hid_t dst) { - flt_t src_type, dst_type; /*data types */ const size_t ntests=NTESTS; /*number of tests */ - const size_t nelmts=NTESTELEM; /*num values per test */ - const size_t max_fails=8; /*max number of failures*/ + const size_t nelmts=NTESTELEM; /*num values per test */ + const size_t max_fails=20; /*max number of failures*/ size_t fails_all_tests=0; /*number of failures */ size_t fails_this_test; /*fails for this test */ - const char *src_type_name = NULL; /*source type name */ - const char *dst_type_name = NULL; /*destination type name */ - size_t src_size, dst_size; /*type sizes */ - unsigned char *buf = NULL; /*buffer for conversion */ - unsigned char *saved = NULL; /*original values */ char str[256]; /*hello string */ - float hw_f; /*hardware-converted */ - double hw_d; /*hardware-converted */ - void *aligned=NULL; /*aligned buffer */ -#if H5_SIZEOF_LONG_DOUBLE!=H5_SIZEOF_DOUBLE - long double hw_ld; /*hardware-converted */ -#endif - unsigned char *hw=NULL; /*ptr to hardware-conv'd*/ - size_t i, j, k; /*counters */ + dtype_t src_type; /*data types */ + dtype_t dst_type; /*data types */ + const char *src_type_name=NULL; /*source type name */ + const char *dst_type_name=NULL; /*destination type name */ int endian; /*machine endianess */ + size_t src_size, dst_size; /*type sizes */ + unsigned char *buf=NULL; /*buffer for conversion */ + unsigned char *saved=NULL; /*original values */ + size_t i, j, k; /*counters */ + unsigned char *hw=NULL; /*hardware conv result */ + unsigned char src_bits[32]; /*src value in LE order */ + unsigned char dst_bits[32]; /*dest value in LE order*/ + size_t src_nbits; /*source length in bits */ + size_t dst_nbits; /*dst length in bits */ + void *aligned=NULL; /*aligned temp buffer */ + float hw_float; + double hw_double; + long double hw_ldouble; + signed char hw_char; + unsigned char hw_uchar; + short hw_short; + unsigned short hw_ushort; + int hw_int; + unsigned hw_uint; + long hw_long; + unsigned long hw_ulong; + long_long hw_llong; + unsigned long_long hw_ullong; -#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; - } - } -#endif - - /* - * The remainder of this function is executed only by the child if - * HANDLE_SIGFPE is defined. - */ -#ifndef __WATCOMC__ - signal(SIGFPE,fpe_handler); -#endif - - /* What are the names of the source and destination types */ - if (H5Tequal(src, H5T_NATIVE_FLOAT)) { + /* What is the name of the source type */ + if (H5Tequal(src, H5T_NATIVE_SCHAR)) { + src_type_name = "signed char"; + src_type = INT_CHAR; + } else if (H5Tequal(src, H5T_NATIVE_UCHAR)) { + src_type_name = "unsigned char"; + src_type = INT_UCHAR; + } else if (H5Tequal(src, H5T_NATIVE_SHORT)) { + src_type_name = "short"; + src_type = INT_SHORT; + } else if (H5Tequal(src, H5T_NATIVE_USHORT)) { + src_type_name = "unsigned short"; + src_type = INT_USHORT; + } else if (H5Tequal(src, H5T_NATIVE_INT)) { + src_type_name = "int"; + src_type = INT_INT; + } else if (H5Tequal(src, H5T_NATIVE_UINT)) { + src_type_name = "unsigned int"; + src_type = INT_UINT; + } else if (H5Tequal(src, H5T_NATIVE_LONG)) { + src_type_name = "long"; + src_type = INT_LONG; + } else if (H5Tequal(src, H5T_NATIVE_ULONG)) { + src_type_name = "unsigned long"; + src_type = INT_ULONG; + } else if (H5Tequal(src, H5T_NATIVE_LLONG)) { + src_type_name = "long long"; + src_type = INT_LLONG; + } else if (H5Tequal(src, H5T_NATIVE_ULLONG)) { + src_type_name = "unsigned long long"; + src_type = INT_ULLONG; + } else if (H5Tequal(src, H5T_NATIVE_FLOAT)) { src_type_name = "float"; src_type = FLT_FLOAT; } else if (H5Tequal(src, H5T_NATIVE_DOUBLE)) { @@ -3996,10 +3968,41 @@ test_conv_flt_1 (const char *name, hid_t src, hid_t dst) #endif } else { src_type_name = "UNKNOWN"; - src_type = FLT_OTHER; + src_type = OTHER; } - - if (H5Tequal(dst, H5T_NATIVE_FLOAT)) { + + /* What is the name of the destination type */ + if (H5Tequal(dst, H5T_NATIVE_SCHAR)) { + dst_type_name = "signed char"; + dst_type = INT_CHAR; + } else if (H5Tequal(dst, H5T_NATIVE_UCHAR)) { + dst_type_name = "unsigned char"; + dst_type = INT_UCHAR; + } else if (H5Tequal(dst, H5T_NATIVE_SHORT)) { + dst_type_name = "short"; + dst_type = INT_SHORT; + } else if (H5Tequal(dst, H5T_NATIVE_USHORT)) { + dst_type_name = "unsigned short"; + dst_type = INT_USHORT; + } else if (H5Tequal(dst, H5T_NATIVE_INT)) { + dst_type_name = "int"; + dst_type = INT_INT; + } else if (H5Tequal(dst, H5T_NATIVE_UINT)) { + dst_type_name = "unsigned int"; + dst_type = INT_UINT; + } else if (H5Tequal(dst, H5T_NATIVE_LONG)) { + dst_type_name = "long"; + dst_type = INT_LONG; + } else if (H5Tequal(dst, H5T_NATIVE_ULONG)) { + dst_type_name = "unsigned long"; + dst_type = INT_ULONG; + } else if (H5Tequal(dst, H5T_NATIVE_LLONG)) { + dst_type_name = "long long"; + dst_type = INT_LLONG; + } else if (H5Tequal(dst, H5T_NATIVE_ULLONG)) { + dst_type_name = "unsigned long long"; + dst_type = INT_ULLONG; + } else if (H5Tequal(dst, H5T_NATIVE_FLOAT)) { dst_type_name = "float"; dst_type = FLT_FLOAT; } else if (H5Tequal(dst, H5T_NATIVE_DOUBLE)) { @@ -4012,13 +4015,11 @@ test_conv_flt_1 (const char *name, hid_t src, hid_t dst) #endif } else { dst_type_name = "UNKNOWN"; - dst_type = FLT_OTHER; + dst_type = OTHER; } /* Sanity checks */ - if(sizeof(float)==sizeof(double)) - puts("Sizeof(float)==sizeof(double) - some tests may not be sensible."); - if (FLT_OTHER==src_type || FLT_OTHER==dst_type) { + if (OTHER==src_type || OTHER==dst_type) { sprintf(str, "Testing random %s %s -> %s conversions", name, src_type_name, dst_type_name); printf("%-70s", str); @@ -4026,24 +4027,48 @@ test_conv_flt_1 (const char *name, hid_t src, hid_t dst) puts(" Unknown data type."); goto error; } - + + if ((INT_CHAR==src_type || INT_UCHAR==src_type || INT_SHORT==src_type || + INT_USHORT==src_type || INT_INT==src_type || INT_UINT==src_type || + INT_LONG==src_type || INT_ULONG==src_type || INT_LLONG==src_type || + INT_ULLONG==src_type) && + (FLT_FLOAT!=dst_type && FLT_DOUBLE!=dst_type && FLT_LDOUBLE!=dst_type)) { + sprintf(str, "Testing random %s %s -> %s conversions", + name, src_type_name, dst_type_name); + printf("%-70s", str); + H5_FAILED(); + puts(" 1. Not an integer-float conversion."); + goto error; + } + + if ((FLT_FLOAT==src_type || FLT_DOUBLE==src_type || FLT_LDOUBLE==src_type) + && (INT_CHAR!=dst_type && INT_UCHAR!=dst_type && INT_SHORT!=dst_type + && INT_USHORT!=dst_type && INT_INT!=dst_type && INT_UINT!=dst_type + && INT_LONG!=dst_type && INT_ULONG!=dst_type && INT_LLONG!=dst_type + && INT_ULLONG!=dst_type)) { + sprintf(str, "Testing random %s %s -> %s conversions", + name, src_type_name, dst_type_name); + printf("%-70s", str); + H5_FAILED(); + puts(" 2. Not a float-integer conversion."); + goto error; + } + /* Allocate buffers */ - endian = H5Tget_order(H5T_NATIVE_FLOAT); + endian = H5Tget_order(H5T_NATIVE_INT); src_size = H5Tget_size(src); dst_size = H5Tget_size(dst); - buf = aligned_malloc(nelmts*MAX(src_size, dst_size)); + src_nbits = H5Tget_precision(src); /* not 8*src_size, esp on J90 - QAK */ + dst_nbits = H5Tget_precision(dst); /* not 8*dst_size, esp on J90 - QAK */ + buf = aligned_malloc(nelmts*MAX(src_size, dst_size)); saved = aligned_malloc(nelmts*MAX(src_size, dst_size)); - aligned = malloc(16); /*should be big enough for any type*/ + aligned = malloc(sizeof(long_long)); #ifdef SHOW_OVERFLOWS noverflows_g = 0; #endif + /* The tests */ for (i=0; i1) { sprintf(str, "Testing random %s %s -> %s conversions (test %d/%d)", name, src_type_name, dst_type_name, (int)i+1, (int)ntests); @@ -4053,21 +4078,986 @@ test_conv_flt_1 (const char *name, hid_t src, hid_t dst) } printf("%-70s", str); fflush(stdout); - fails_this_test = 0; + fails_this_test=0; /* * Initialize the source buffers to random bits. The `buf' buffer * will be used for the conversion while the `saved' buffer will be - * used for the comparison later. + * sed for the comparison later. */ - if (!skip_overflow_tests_g) { - for (j=0; j=max_fails) { + puts(" maximum failures reached, aborting test..."); + goto done; + } + } + PASSED(); + } +#ifdef SHOW_OVERFLOWS + if (noverflows_g>0) { + printf(" %d overflow%s in previous test\n", + noverflows_g, 1==noverflows_g?"":"s"); + } +#endif + + done: + if (buf) aligned_free(buf); + if (saved) aligned_free(saved); + if (aligned) free(aligned); + fflush(stdout); + reset_hdf5(); /*print statistics*/ + return (int)fails_all_tests; + + error: + if (buf) aligned_free(buf); + if (saved) aligned_free(saved); + if (aligned) free(aligned); + fflush(stdout); + reset_hdf5(); /*print statistics*/ + return MAX((int)fails_all_tests, 1); +} + + +/*------------------------------------------------------------------------- + * Function: overflows + * + * Purpose: return the index of the most significant digit in a bit + * vector. + * + * Return: index + * + * Programmer: Raymond Lu + * Monday, Nov 17, 2003 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +hbool_t +overflows(unsigned char *origin_bits, dtype_t src_dtype, size_t src_size_bytes, size_t dst_num_bits) +{ + hbool_t ret_value=FALSE; + hsize_t expt, sig; + size_t frct_digits=0, expt_digits=0, bias=0; + ssize_t indx; + unsigned char bits[32]; + + memcpy(bits, origin_bits, src_size_bytes); + + if(src_size_bytes==4) { + frct_digits = 23; + expt_digits = 8; + bias = 0x7f; + } else if(src_size_bytes==8) { + frct_digits = 52; + expt_digits = 11; + bias = 0x3ff; + } + + /* get exponent */ + expt = H5T_bit_get_d(bits, frct_digits, expt_digits) - bias; + + if(expt>=(dst_num_bits-1)) { + ret_value=TRUE; + goto done; + } + + /* get significand */ + sig = H5T_bit_get_d(bits, 0, frct_digits); + + /* restore implicit bit*/ + sig |= (hsize_t)1<expt_digits) + sig <<= expt - expt_digits; + else + sig >>= expt_digits - expt; + + indx = H5T_bit_find(&sig, 0, 8*sizeof(hsize_t), H5T_BIT_MSB, 1); + + if(indx>=dst_num_bits) + ret_value=TRUE; + + free(bits); + +done: + return ret_value; +} + + +/*------------------------------------------------------------------------- + * 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(dtype_t type, void *val) +{ + int retval; + char s[256]; + + if (FLT_FLOAT==type) { + float x; + memcpy(&x, val, sizeof(float)); + retval = (x!=x); + } else if (FLT_DOUBLE==type) { + double x; + memcpy(&x, val, sizeof(double)); + retval = (x!=x); +#if H5_SIZEOF_LONG_DOUBLE!=H5_SIZEOF_DOUBLE + } else if (FLT_LDOUBLE==type) { + long double x; + memcpy(&x, val, sizeof(long double)); + retval = (x!=x); +#endif + } else { + 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) { + if (FLT_FLOAT==type) { + float x; + memcpy(&x, val, sizeof(float)); + sprintf(s, "%g", x); + } else if (FLT_DOUBLE==type) { + double x; + memcpy(&x, val, sizeof(double)); + sprintf(s, "%g", x); +#if H5_SIZEOF_LONG_DOUBLE!=H5_SIZEOF_DOUBLE + } else if (FLT_LDOUBLE==type) { + long double x; + memcpy(&x, val, sizeof(long double)); + sprintf(s, "%Lg", x); +#endif + } else { + return 0; + } + /* Bug here. Ought to be + * if (strstr(s, "NaN") || strstr(s, "NAN") || strstr(s, "nan")) + */ + 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 + * DST. These types should be H5T_NATIVE_FLOAT, + * H5T_NATIVE_DOUBLE, or H5T_NATIVE_LDOUBLE. + * + * Return: Success: 0 + * + * Failure: number of errors + * + * Programmer: Robb Matzke + * Tuesday, June 23, 1998 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +static int +test_conv_flt_1 (const char *name, hid_t src, hid_t dst) +{ + dtype_t src_type, dst_type; /*data types */ + const size_t ntests=NTESTS; /*number of tests */ + const size_t nelmts=NTESTELEM; /*num values per test */ + const size_t max_fails=8; /*max number of failures*/ + size_t fails_all_tests=0; /*number of failures */ + size_t fails_this_test; /*fails for this test */ + const char *src_type_name = NULL; /*source type name */ + const char *dst_type_name = NULL; /*destination type name */ + size_t src_size, dst_size; /*type sizes */ + unsigned char *buf = NULL; /*buffer for conversion */ + unsigned char *saved = NULL; /*original values */ + char str[256]; /*hello string */ + float hw_f; /*hardware-converted */ + double hw_d; /*hardware-converted */ + void *aligned=NULL; /*aligned buffer */ +#if H5_SIZEOF_LONG_DOUBLE!=H5_SIZEOF_DOUBLE + long double hw_ld; /*hardware-converted */ +#endif + unsigned char *hw=NULL; /*ptr to hardware-conv'd*/ + 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; + } + } +#endif + + /* + * The remainder of this function is executed only by the child if + * HANDLE_SIGFPE is defined. + */ +#ifndef __WATCOMC__ + 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"; + src_type = FLT_FLOAT; + } else if (H5Tequal(src, H5T_NATIVE_DOUBLE)) { + src_type_name = "double"; + src_type = FLT_DOUBLE; +#if H5_SIZEOF_LONG_DOUBLE!=H5_SIZEOF_DOUBLE + } else if (H5Tequal(src, H5T_NATIVE_LDOUBLE)) { + src_type_name = "long double"; + src_type = FLT_LDOUBLE; +#endif + } else { + src_type_name = "UNKNOWN"; + src_type = OTHER; + } + + if (H5Tequal(dst, H5T_NATIVE_FLOAT)) { + dst_type_name = "float"; + dst_type = FLT_FLOAT; + } else if (H5Tequal(dst, H5T_NATIVE_DOUBLE)) { + dst_type_name = "double"; + dst_type = FLT_DOUBLE; +#if H5_SIZEOF_LONG_DOUBLE!=H5_SIZEOF_DOUBLE + } else if (H5Tequal(dst, H5T_NATIVE_LDOUBLE)) { + dst_type_name = "long double"; + dst_type = FLT_LDOUBLE; +#endif + } else { + dst_type_name = "UNKNOWN"; + dst_type = OTHER; + } + + /* Sanity checks */ + if(sizeof(float)==sizeof(double)) + puts("Sizeof(float)==sizeof(double) - some tests may not be sensible."); + if (OTHER==src_type || OTHER==dst_type) { + sprintf(str, "Testing random %s %s -> %s conversions", + name, src_type_name, dst_type_name); + printf("%-70s", str); + H5_FAILED(); + puts(" Unknown data type."); + goto error; + } + + /* Allocate buffers */ + endian = H5Tget_order(H5T_NATIVE_FLOAT); + src_size = H5Tget_size(src); + dst_size = H5Tget_size(dst); + buf = aligned_malloc(nelmts*MAX(src_size, dst_size)); + saved = aligned_malloc(nelmts*MAX(src_size, dst_size)); + aligned = malloc(16); /*should be big enough for any type*/ +#ifdef SHOW_OVERFLOWS + noverflows_g = 0; +#endif + + for (i=0; i1) { + sprintf(str, "Testing random %s %s -> %s conversions (test %d/%d)", + name, src_type_name, dst_type_name, (int)i+1, (int)ntests); + } else { + sprintf(str, "Testing random %s %s -> %s conversions", + name, src_type_name, dst_type_name); + } + printf("%-70s", str); + fflush(stdout); + fails_this_test = 0; + + /* + * Initialize the source buffers to random bits. The `buf' buffer + * will be used for the conversion while the `saved' buffer will be + * used for the comparison later. + */ + if (!skip_overflow_tests_g) { + for (j=0; j