summaryrefslogtreecommitdiffstats
path: root/test/dtypes.c
diff options
context:
space:
mode:
authorRobb Matzke <matzke@llnl.gov>1998-06-30 21:30:28 (GMT)
committerRobb Matzke <matzke@llnl.gov>1998-06-30 21:30:28 (GMT)
commit1b3a1f8014b630208013c7a18cfe8e7c0539e161 (patch)
tree442600fb6f75f8dbde490f48d2a8ccba7c823164 /test/dtypes.c
parent030d46c078b7ef61468703dabb4861212ecb13ca (diff)
downloadhdf5-1b3a1f8014b630208013c7a18cfe8e7c0539e161.zip
hdf5-1b3a1f8014b630208013c7a18cfe8e7c0539e161.tar.gz
hdf5-1b3a1f8014b630208013c7a18cfe8e7c0539e161.tar.bz2
[svn-r437] Changes since 19980612
---------------------- ./src/H5Tbit.c ./src/H5Tpkg.h Fixed a bug in H5T_bit_copy(). Added H5T_bit_get_d() and H5T_bit_set_d() which treat portions of a bit vector as an unsigned integer. Added H5T_bit_inc() that increments part of a bit vector and returns an indication of overflow. ./src/H5Tconv.c ./src/H5Tpkg.h ./test/dtypes.c Added a slow general floating point conversion which works so far on Intel, MIPS, and DEC but the test is turned off because a cast from double to float will cause a SIGFPE on some systems if an overflow occurs. Added fast hardware conversions between native floating point types. This function is also subject to the SIGFPE problem. ./src/H5detect.c Removed the exponent bias adjustment when the significand isn't normalized. This is now handled in the conversion functions instead. ./src/H5T.c Register new conversion functions. Plugged a memory leak in the library termination code. ./RELEASE Added a list of major changes since the first alpha. ./src/H5.c ./src/H5private.h ./src/H5A.c ./src/H5AC.c ./src/H5D.c ./src/H5Ffamily.c ./src/H5Fistore.c ./src/H5G.c ./src/H5Gprivate.h ./src/H5HG.c ./src/H5O.c ./src/H5T.c ./src/H5Tbit.c ./src/H5Tconv.c Fixed various compiler warnings on Irix64. ./src/H5MM.c Added PABLO_MASK to this file. ./test/chunk.c Removed a warning about memcpy().
Diffstat (limited to 'test/dtypes.c')
-rw-r--r--test/dtypes.c351
1 files changed, 342 insertions, 9 deletions
diff --git a/test/dtypes.c b/test/dtypes.c
index 1bc58f5..455fd3b 100644
--- a/test/dtypes.c
+++ b/test/dtypes.c
@@ -7,11 +7,17 @@
*
* Purpose: Tests the data type interface (H5T)
*/
+#include <assert.h>
#include <hdf5.h>
+#include <math.h>
+#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
+#define H5T_PACKAGE
+#include <H5Tpkg.h> /*to turn off hardware conversions*/
+
#include <H5config.h>
#ifndef HAVE_ATTRIBUTE
# undef __attribute__
@@ -21,6 +27,11 @@
# define __unused__ __attribute__((unused))
#endif
+#ifndef MAX
+# define MAX(X,Y) ((X)>(Y)?(X):(Y))
+# define MIN(X,Y) ((X)<(Y)?(X):(Y))
+#endif
+
#define FILE_NAME_1 "dtypes1.h5"
#define FILE_NAME_2 "dtypes2.h5"
@@ -29,6 +40,17 @@ typedef struct complex_t {
double im;
} complex_t;
+/*
+ * Count up or down depending on whether the machine is big endian or little
+ * endian. If `E' is H5T_ORDER_BE then the result will be I, otherwise the
+ * result will be Z-(I+1).
+ */
+#define ENDIAN(E,Z,I) (H5T_ORDER_BE==(E)?(I):(Z)-((I)+1))
+
+typedef enum flt_t {
+ FLT_FLOAT, FLT_DOUBLE, FLT_LDOUBLE, FLT_OTHER
+} flt_t;
+
/*-------------------------------------------------------------------------
* Function: cleanup
@@ -499,7 +521,7 @@ test_named (void)
/*-------------------------------------------------------------------------
- * Function: test_conv_num
+ * Function: test_conv_int
*
* Purpose: Test atomic number conversions.
*
@@ -515,7 +537,7 @@ test_named (void)
*-------------------------------------------------------------------------
*/
static herr_t
-test_conv_num (void)
+test_conv_int (void)
{
const size_t ntests=100;
const size_t nelmts=2000;
@@ -528,7 +550,7 @@ test_conv_num (void)
* Test some specific overflow/underflow cases.
*---------------------------------------------------------------------
*/
- printf ("%-70s", "Testing atomic number overflow conversions");
+ printf ("%-70s", "Testing integer overflow conversions");
fflush (stdout);
/* (unsigned)0x80000000 -> (unsigned)0xffff */
@@ -608,7 +630,7 @@ test_conv_num (void)
* Test random cases.
*-----------------------------------------------------------------------
*/
- printf ("%-70s", "Testing atomic number random conversions");
+ printf ("%-70s", "Testing random integer conversions");
fflush (stdout);
/* Allocate buffers */
@@ -650,7 +672,289 @@ test_conv_num (void)
return -1;
}
-
+
+/*-------------------------------------------------------------------------
+ * 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: -1
+ *
+ * Programmer: Robb Matzke
+ * Tuesday, June 23, 1998
+ *
+ * Modifications:
+ *
+ *-------------------------------------------------------------------------
+ */
+static int
+test_conv_flt_1 (const char *name, hid_t src, hid_t dst)
+{
+ flt_t src_type, dst_type; /*data types */
+ const size_t ntests=10; /*number of tests */
+ const size_t nelmts=200000; /*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 */
+ long double hw_ld; /*hardware-converted */
+ unsigned char *hw=NULL; /*ptr to hardware-conv'd*/
+ size_t i, j, k; /*counters */
+ int endian; /*machine endianess */
+
+ /* 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;
+ } else if (H5Tequal(src, H5T_NATIVE_LDOUBLE)) {
+ src_type_name = "long double";
+ src_type = FLT_LDOUBLE;
+ } else {
+ src_type_name = "UNKNOWN";
+ src_type = FLT_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;
+ } else if (H5Tequal(dst, H5T_NATIVE_LDOUBLE)) {
+ dst_type_name = "long double";
+ dst_type = FLT_LDOUBLE;
+ } else {
+ dst_type_name = "UNKNOWN";
+ dst_type = FLT_OTHER;
+ }
+
+ /* Sanity checks */
+ assert(sizeof(float)!=sizeof(double));
+ if (FLT_OTHER==src_type || FLT_OTHER==dst_type) {
+ sprintf(str, "Testing random %s %s -> %s conversions",
+ name, src_type_name, dst_type_name);
+ printf ("%-70s", str);
+ puts("*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 = malloc(nelmts*MAX(src_size, dst_size));
+ saved = malloc(nelmts*MAX(src_size, dst_size));
+
+ for (i=0; i<ntests; i++) {
+
+ /*
+ * If it looks like it might take a long time then print a progress
+ * report between each test.
+ */
+ sprintf(str, "Testing random %s %s -> %s conversions (test %d/%d)",
+ name, src_type_name, dst_type_name, (int)i+1, (int)ntests);
+ 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.
+ */
+ for (j=0; j<nelmts*src_size; j++) buf[j] = saved[j] = rand();
+
+ /* Perform the conversion in software */
+ if (H5Tconvert(src, dst, nelmts, buf, NULL)<0) goto error;
+
+ /* Check the software results against the hardware */
+ for (j=0; j<nelmts; j++) {
+
+ /* The hardware conversion */
+ if (FLT_FLOAT==src_type) {
+ if (FLT_FLOAT==dst_type) {
+ hw_f = ((float*)saved)[j];
+ hw = (unsigned char*)&hw_f;
+ } else if (FLT_DOUBLE==dst_type) {
+ hw_d = ((float*)saved)[j];
+ hw = (unsigned char*)&hw_d;
+ } else {
+ hw_ld = ((float*)saved)[j];
+ hw = (unsigned char*)&hw_ld;
+ }
+ } else if (FLT_DOUBLE==src_type) {
+ if (FLT_FLOAT==dst_type) {
+ hw_f = ((double*)saved)[j];
+ hw = (unsigned char*)&hw_f;
+ } else if (FLT_DOUBLE==dst_type) {
+ hw_d = ((double*)saved)[j];
+ hw = (unsigned char*)&hw_d;
+ } else {
+ hw_ld = ((double*)saved)[j];
+ hw = (unsigned char*)&hw_ld;
+ }
+ } else {
+ if (FLT_FLOAT==dst_type) {
+ hw_f = ((long double*)saved)[j];
+ hw = (unsigned char*)&hw_f;
+ } else if (FLT_DOUBLE==dst_type) {
+ hw_d = ((long double*)saved)[j];
+ hw = (unsigned char*)&hw_d;
+ } else {
+ hw_ld = ((long double*)saved)[j];
+ hw = (unsigned char*)&hw_ld;
+ }
+ }
+
+ /* Are the two results the same? */
+ for (k=0; k<dst_size; k++) {
+ if (buf[j*dst_size+k]!=hw[k]) break;
+ }
+ if (k==dst_size) continue; /*no error*/
+
+#if 1
+ /*
+ * Assume same if both results are NaN. There are many NaN bit
+ * patterns and the software doesn't attemt to emulate the
+ * hardware in this regard. Instead, software uses a single bit
+ * 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]) {
+ continue;
+ } else if (FLT_DOUBLE==dst_type &&
+ ((double*)buf)[j]!=((double*)buf)[j] &&
+ ((double*)hw)[0]!=((double*)hw)[0]) {
+ continue;
+ } else if (FLT_LDOUBLE==dst_type &&
+ ((long double*)buf)[j]!=((long double*)buf)[j] &&
+ ((long double*)hw)[0]!=((long double*)hw)[0]) {
+ continue;
+ }
+#endif
+
+#if 1
+ /*
+ * Assume same if hardware result is NaN. This is because the
+ * 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;
+ }
+#endif
+
+#if 1
+ /*
+ * Instead of matching down to the bit, just make sure the
+ * exponents are the same and the mantissa is the same to a
+ * certain precision. This is needed on machines that don't
+ * round as expected.
+ */
+ {
+ double check_mant[2];
+ int check_expo[2];
+
+ if (FLT_FLOAT==dst_type) {
+ check_mant[0] = frexp(((float*)buf)[j], check_expo+0);
+ check_mant[1] = frexp(((float*)hw)[0], check_expo+1);
+ } else if (FLT_DOUBLE==dst_type) {
+ check_mant[0] = frexp(((double*)buf)[j], check_expo+0);
+ check_mant[1] = frexp(((double*)hw)[0], check_expo+1);
+ } else {
+ check_mant[0] = frexp(((long double*)buf)[j],check_expo+0);
+ check_mant[1] = frexp(((long double*)hw)[0],check_expo+1);
+ }
+ if (check_expo[0]==check_expo[1] &&
+ fabs(check_mant[0]-check_mant[1])<0.000001) {
+ continue;
+ }
+ }
+#endif
+
+ if (0==fails_this_test++) puts("*FAILED*");
+ printf(" test %u, elmt %u\n", (unsigned)i+1, (unsigned)j);
+
+ printf(" src =");
+ for (k=0; k<src_size; k++) {
+ printf(" %02x", saved[j*src_size+ENDIAN(endian,src_size,k)]);
+ }
+ printf("%*s", 3*MAX(0, (ssize_t)dst_size-(ssize_t)src_size), "");
+ if (FLT_FLOAT==src_type) {
+ printf(" %29.20e\n", ((float*)saved)[j]);
+ } else if (FLT_DOUBLE==src_type) {
+ printf(" %29.20e\n", ((double*)saved)[j]);
+ } else {
+ printf(" %29.20Le\n", ((long double*)saved)[j]);
+ }
+
+ printf(" dst =");
+ for (k=0; k<dst_size; k++) {
+ printf(" %02x", buf[j*dst_size+ENDIAN(endian,dst_size,k)]);
+ }
+ printf("%*s", 3*MAX(0, (ssize_t)src_size-(ssize_t)dst_size), "");
+ if (FLT_FLOAT==dst_type) {
+ printf(" %29.20e\n", ((float*)buf)[j]);
+ } else if (FLT_DOUBLE==dst_type) {
+ printf(" %29.20e\n", ((double*)buf)[j]);
+ } else {
+ printf(" %29.20Le\n", ((long double*)buf)[j]);
+ }
+
+ printf(" ans =");
+ for (k=0; k<dst_size; k++) {
+ printf(" %02x", hw[ENDIAN(endian,dst_size,k)]);
+ }
+ printf("%*s", 3*MAX(0, (ssize_t)src_size-(ssize_t)dst_size), "");
+ if (FLT_FLOAT==dst_type) {
+ printf(" %29.20e\n", hw_f);
+ } else if (FLT_DOUBLE==dst_type) {
+ printf(" %29.20e\n", hw_d);
+ } else {
+ printf(" %29.20Le\n", hw_ld);
+ }
+
+ if (++fails_all_tests>=max_fails) {
+ puts(" maximum failures reached, aborting test...");
+ goto done;
+ }
+ }
+ puts(" PASSED");
+ }
+
+ done:
+ if (buf) free (buf);
+ if (saved) free (saved);
+ return (int)fails_all_tests;
+
+ error:
+ if (buf) free (buf);
+ if (saved) free (saved);
+ return (int)MIN(1, fails_all_tests);
+}
/*-------------------------------------------------------------------------
@@ -672,7 +976,11 @@ test_conv_num (void)
int
main(void)
{
- int nerrors = 0;
+ unsigned long nerrors = 0;
+
+#if 0
+ signal(SIGFPE,SIG_IGN);
+#endif
/* Set the error handler */
H5Eset_auto (display_error_cb, NULL);
@@ -683,11 +991,36 @@ main(void)
nerrors += test_compound()<0 ? 1 : 0;
nerrors += test_transient ()<0 ? 1 : 0;
nerrors += test_named ()<0 ? 1 : 0;
- nerrors += test_conv_num ()<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);
+
+ /* Test hardware conversion functions */
+ nerrors += test_conv_flt_1("hw", H5T_NATIVE_FLOAT, H5T_NATIVE_DOUBLE);
+ nerrors += test_conv_flt_1("hw", H5T_NATIVE_DOUBLE, H5T_NATIVE_FLOAT);
+
+ /* Test software conversion functions */
+ H5Tunregister(H5T_conv_float_double);
+ H5Tunregister(H5T_conv_double_float);
+ nerrors += test_conv_flt_1("sw", H5T_NATIVE_FLOAT, H5T_NATIVE_DOUBLE);
+ nerrors += test_conv_flt_1("sw", H5T_NATIVE_FLOAT, H5T_NATIVE_LDOUBLE);
+ nerrors += test_conv_flt_1("sw", H5T_NATIVE_DOUBLE, H5T_NATIVE_FLOAT);
+ 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("***** %d DATA TYPE TEST%s FAILED! *****\n",
- nerrors, 1 == nerrors ? "" : "S");
+ printf("***** %lu FAILURE%s! *****\n",
+ nerrors, 1==nerrors?"":"S");
exit(1);
}
printf("All data type tests passed.\n");