From 1b3a1f8014b630208013c7a18cfe8e7c0539e161 Mon Sep 17 00:00:00 2001 From: Robb Matzke Date: Tue, 30 Jun 1998 16:30:28 -0500 Subject: [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(). --- MANIFEST | 1 + RELEASE | 78 +++++++++ config/irix5.3 | 2 +- src/H5.c | 8 +- src/H5A.c | 14 +- src/H5AC.c | 2 +- src/H5D.c | 2 - src/H5Distore.c | 2 +- src/H5Ffamily.c | 4 +- src/H5Fistore.c | 2 +- src/H5G.c | 4 +- src/H5Gprivate.h | 2 +- src/H5HG.c | 2 +- src/H5MM.c | 1 + src/H5O.c | 10 +- src/H5T.c | 23 ++- src/H5Tbit.c | 176 +++++++++++++++++++- src/H5Tconv.c | 500 ++++++++++++++++++++++++++++++++++++++++++++++++++++++- src/H5Tpkg.h | 9 + src/H5detect.c | 9 +- src/H5private.h | 1 - test/.distdep | 248 +++++++++++++-------------- test/chunk.c | 1 + test/dtypes.c | 351 +++++++++++++++++++++++++++++++++++++- 24 files changed, 1270 insertions(+), 182 deletions(-) diff --git a/MANIFEST b/MANIFEST index 6ea1e83..0ddf81b 100644 --- a/MANIFEST +++ b/MANIFEST @@ -1,3 +1,4 @@ +./CHANGES_API ./INSTALL ./INSTALL.ascired ./INSTALL.ibm.sp.parallel diff --git a/RELEASE b/RELEASE index 09df2a6..c0d3b27 100644 --- a/RELEASE +++ b/RELEASE @@ -1,6 +1,84 @@ Release information for hdf5-1.0.0a ----------------------------------- + CHANGES SINCE THE FIRST ALPHA + +* Two of the packages have been renamed. The data space API has been + renamed from `H5P' to `H5S' and the property list (template) API has + been renamed from `H5C' to `H5P'. + +* The new attribute API `H5A' has been added. An attribute is a small + dataset which can be attached to some other object (for instance, a + 4x4 transformation matrix attached to a 3-dimensional dataset, or an + English abstract attached to a group). + +* The error handling API `H5E' has been completed. By default, when an + API function returns failure an error stack is displayed on the + standard error stream. The H5Eset_auto() controls the automatic + printing and H5E_BEGIN_TRY/H5E_END_TRY macros can temporarily + disable the automatic error printing. + +* Support for large files and datasets (>2GB) has been added. There + is an html document that describes how it works. Some of the types + for function arguments have changed to support this: all arguments + pertaining to sizes of memory objects are `size_t' and all arguments + pertaining to file sizes are `hsize_t'. + +* More data type conversions have been added although none of them are + fine tuned for performance. There are new converters from integer + to integer and float to float, but not between integers and floating + points. A bug has been fixed in the converter between compound + types. + +* The numbered types have been removed from the API: int8, uint8, + int16, uint16, int32, uint32, int64, uint64, float32, and float64. + Use standard C types instead. Similarly, the numbered types were + removed from the H5T_NATIVE_* architecture; use unnumbered types + which correspond to the standard C types like H5T_NATIVE_INT. + +* More debugging support was added. If tracing is enabled at + configuration time and the HDF5_TRACE environment variable is set to + a file descriptor then all API calls will emit the function name, + argument names and values, and return value on that file number. + There is an html document that describes this. If appropriate + debugging options are enabled at configuration time, some packages + will display performance information on stderr. + +* Data types can be stored in the file as independent objects and + multiple datasets can share a data type. + +* The raw data I/O stream has been implemented and the application can + control meta and raw data caches, so I/O performance should be + improved from the first alpha release. + +* Group and attribute query functions have been implemented so it is + now possible to find out the contents of a file with no prior + knowledge. + +* External raw data storage allows datasets to be written by other + applications or I/O libraries and described and accessed through + HDF5. + +* Hard and soft (symbolic) links are implemented which allow groups to + share objects. + +* User-defined data compression is implemented although we may + generalize the interface to allow arbitrary user-defined filters + which can be used for compression, checksums, encryption, + performance monitoring, etc. The publicly-available `deflate' + method is predefined if the GNU libz.a can be found at configuration + time. + +* The configuration scripts have been modified to make it easier to + build debugging vs. production versions of the library. + +* The library automatically checks that the application was compiled + with the correct version of header files. + +* Parallel feature changes...(?) + + LIST OF API FUNCTIONS + The following functions are implemented. Errors are returned if an attempt is made to use some feature which is not implemented and printing the error stack will show `not implemented yet'. diff --git a/config/irix5.3 b/config/irix5.3 index acc375e..c0064ef 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 -ansi -fullwarn -woff 799" +CFLAGS="$CFLAGS -U_POSIX_SOURCE -ansi -fullwarn -woff 799" #CPPFLAGS="$CPPFLAGS -I." # What compiler flags should be used for code development? diff --git a/src/H5.c b/src/H5.c index 71defe7..8f770b9 100644 --- a/src/H5.c +++ b/src/H5.c @@ -591,7 +591,7 @@ HDfprintf (FILE *stream, const char *fmt, ...) if (prec>0) { sprintf (template+strlen (template), ".%d", prec); } - if (modifier) { + if (*modifier) { sprintf (template+strlen (template), "%s", modifier); } sprintf (template+strlen (template), "%c", conv); @@ -1281,24 +1281,26 @@ H5_trace (hbool_t returning, const char *func, const char *type, ...) case 'M': switch (type[1]) { -#ifdef HAVE_PARALLEL case 'c': if (ptr) { fprintf (out, "0x%lx", (unsigned long)vp); } else { +#ifdef HAVE_PARALLEL MPI_Comm comm = va_arg (ap, MPI_Comm); fprintf (out, "%ld", (long)comm); +#endif } break; case 'i': if (ptr) { fprintf (out, "0x%lx", (unsigned long)vp); } else { +#ifdef HAVE_PARALLEL MPI_Info info = va_arg (ap, MPI_Info); fprintf (out, "%ld", (long)info); +#endif } break; -#endif default: goto error; } diff --git a/src/H5A.c b/src/H5A.c index d7014b6..b07bf37 100644 --- a/src/H5A.c +++ b/src/H5A.c @@ -157,7 +157,6 @@ H5Acreate (hid_t loc_id, const char *name, hid_t datatype, hid_t dataspace, H5G_entry_t *ent = NULL; H5T_t *type = NULL; H5S_t *space = NULL; - const H5D_create_t *create_parms = NULL; hid_t ret_value = FAIL; FUNC_ENTER(H5Acreate, FAIL); @@ -195,14 +194,11 @@ H5Acreate (hid_t loc_id, const char *name, hid_t datatype, hid_t dataspace, NULL == (space = H5I_object(dataspace))) { HRETURN_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a data space"); } - if (H5P_DEFAULT!=create_plist) { - if (H5P_DATASET_CREATE != H5Pget_class(create_plist) || - NULL == (create_parms = H5I_object(create_plist))) { - HRETURN_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, - "not a dataset creation property list"); - } - } else { - create_parms = &H5D_create_dflt; + if (H5P_DEFAULT!=create_plist && + (H5P_DATASET_CREATE != H5Pget_class(create_plist) || + NULL == H5I_object(create_plist))) { + HRETURN_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, + "not a dataset creation property list"); } /* Go do the real work for attaching the attribute to the dataset */ diff --git a/src/H5AC.c b/src/H5AC.c index 0e4b325..c34d7c2 100644 --- a/src/H5AC.c +++ b/src/H5AC.c @@ -722,7 +722,7 @@ H5AC_protect(H5F_t *f, const H5AC_class_t *type, const haddr_t *addr, HRETURN_ERROR (H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed"); } - slot->aprots = na; + slot->aprots = (intn)na; slot->prot = x; } slot->prot[slot->nprots].type = type; diff --git a/src/H5D.c b/src/H5D.c index d696f92..6cbcf2c 100644 --- a/src/H5D.c +++ b/src/H5D.c @@ -972,7 +972,6 @@ H5D_open(H5G_t *loc, const char *name) H5D_t *dataset = NULL; /*the dataset which was found */ H5D_t *ret_value = NULL; /*return value */ intn i; - H5F_t *f = NULL; FUNC_ENTER(H5D_open, NULL); @@ -980,7 +979,6 @@ H5D_open(H5G_t *loc, const char *name) assert (loc); assert (name && *name); - f = H5G_fileof (loc); if (NULL==(dataset = H5MM_calloc(sizeof(H5D_t)))) { HGOTO_ERROR (H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed"); diff --git a/src/H5Distore.c b/src/H5Distore.c index 2f23715..4cb808b 100644 --- a/src/H5Distore.c +++ b/src/H5Distore.c @@ -1086,7 +1086,7 @@ H5F_istore_lock (H5F_t *f, const H5O_layout_t *layout, HGOTO_ERROR (H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed"); } - rdcc->nslots = na; + rdcc->nslots = (intn)na; rdcc->slot = x; } HDmemmove (rdcc->slot+1, rdcc->slot, diff --git a/src/H5Ffamily.c b/src/H5Ffamily.c index bed381f..fd876c0 100644 --- a/src/H5Ffamily.c +++ b/src/H5Ffamily.c @@ -161,7 +161,7 @@ H5F_fam_open(const char *name, const H5F_access_t *access_parms, HGOTO_ERROR (H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed"); } - lf->u.fam.nalloc = na; + lf->u.fam.nalloc = (intn)na; lf->u.fam.memb = x; } lf->u.fam.memb[lf->u.fam.nmemb++] = member; @@ -425,7 +425,7 @@ H5F_fam_write(H5F_low_t *lf, const H5F_access_t *access_parms, HRETURN_ERROR (H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed"); } - lf->u.fam.nalloc = na; + lf->u.fam.nalloc = (intn)na; lf->u.fam.memb = x; } for (i = lf->u.fam.nmemb; i <= membno; i++) { diff --git a/src/H5Fistore.c b/src/H5Fistore.c index 2f23715..4cb808b 100644 --- a/src/H5Fistore.c +++ b/src/H5Fistore.c @@ -1086,7 +1086,7 @@ H5F_istore_lock (H5F_t *f, const H5O_layout_t *layout, HGOTO_ERROR (H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed"); } - rdcc->nslots = na; + rdcc->nslots = (intn)na; rdcc->slot = x; } HDmemmove (rdcc->slot+1, rdcc->slot, diff --git a/src/H5G.c b/src/H5G.c index c885655..f1e65fb 100644 --- a/src/H5G.c +++ b/src/H5G.c @@ -1732,7 +1732,7 @@ H5G_loc (hid_t loc_id) *------------------------------------------------------------------------- */ herr_t -H5G_link (H5G_t *loc, H5G_type_t type, const char *cur_name, +H5G_link (H5G_t *loc, H5G_link_t type, const char *cur_name, const char *new_name) { H5G_entry_t cur_obj; /*entry for the link tail */ @@ -1882,7 +1882,7 @@ H5G_stat (H5G_t *loc, const char *name, hbool_t follow_link, /* * Initialize the stat buf. Symbolic links aren't normal objects and - * therefor don't have much of the normal info. However, the link value + * therefore don't have much of the normal info. However, the link value * length is specific to symbolic links. */ if (statbuf) { diff --git a/src/H5Gprivate.h b/src/H5Gprivate.h index 7c76f2d..ae3064a 100644 --- a/src/H5Gprivate.h +++ b/src/H5Gprivate.h @@ -110,7 +110,7 @@ herr_t H5G_set (H5G_t *grp); herr_t H5G_push (H5G_t *grp); herr_t H5G_pop (H5F_t *f); H5G_t *H5G_getcwg(H5F_t *f); -herr_t H5G_link (H5G_t *loc, H5G_type_t type, const char *cur_name, +herr_t H5G_link (H5G_t *loc, H5G_link_t type, const char *cur_name, const char *new_name); herr_t H5G_stat (H5G_t *loc, const char *name, hbool_t follow_link, H5G_stat_t *statbuf/*out*/); diff --git a/src/H5HG.c b/src/H5HG.c index f2fe211..eaca1f9 100644 --- a/src/H5HG.c +++ b/src/H5HG.c @@ -271,7 +271,7 @@ H5HG_load (H5F_t *f, const haddr_t *addr, const void __unused__ *udata1, HGOTO_ERROR (H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed"); } - heap->nalloc = nalloc; + heap->nalloc = (intn)nalloc; while (pchunk+heap->size) { if (p+H5HG_SIZEOF_OBJHDR(f)>heap->chunk+heap->size) { /* diff --git a/src/H5MM.c b/src/H5MM.c index af38125..bc2a7ef 100644 --- a/src/H5MM.c +++ b/src/H5MM.c @@ -19,6 +19,7 @@ #include /* Interface initialization? */ +#define PABLO_MASK H5MM_mask static hbool_t interface_initialize_g = FALSE; #define INTERFACE_INIT NULL diff --git a/src/H5O.c b/src/H5O.c index 29eb583..dde5917 100644 --- a/src/H5O.c +++ b/src/H5O.c @@ -393,7 +393,7 @@ H5O_load(H5F_t *f, const haddr_t *addr, const void __unused__ *_udata1, HGOTO_ERROR (H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed"); } - oh->alloc_nchunks = na; + oh->alloc_nchunks = (intn)na; oh->chunk = x; } @@ -1455,7 +1455,7 @@ H5O_alloc_extend_chunk(H5O_t *oh, intn chunkno, size_t size) HRETURN_ERROR (H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed"); } - oh->alloc_nmesgs = na; + oh->alloc_nmesgs = (intn)na; oh->mesg = x; } delta = MAX(H5O_MIN_SIZE, size+H5O_SIZEOF_MSGHDR(f)); @@ -1589,7 +1589,7 @@ H5O_alloc_new_chunk(H5F_t *f, H5O_t *oh, size_t size) HRETURN_ERROR (H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed"); } - oh->alloc_nchunks = na; + oh->alloc_nchunks = (intn)na; oh->chunk = x; } chunkno = oh->nchunks++; @@ -1613,7 +1613,7 @@ H5O_alloc_new_chunk(H5F_t *f, H5O_t *oh, size_t size) HRETURN_ERROR (H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed"); } - oh->alloc_nmesgs = na; + oh->alloc_nmesgs = (intn)na; oh->mesg = x; /* Set new object header info to zeros */ @@ -1770,7 +1770,7 @@ H5O_alloc(H5F_t *f, H5O_t *oh, const H5O_class_t *type, size_t size) HRETURN_ERROR (H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed"); } - oh->alloc_nmesgs = na; + oh->alloc_nmesgs = (intn)na; oh->mesg = x; /* Set new object header info to zeros */ diff --git a/src/H5T.c b/src/H5T.c index 9297634..4fe6078 100644 --- a/src/H5T.c +++ b/src/H5T.c @@ -572,6 +572,11 @@ H5T_init_interface(void) HRETURN_ERROR (H5E_DATATYPE, H5E_CANTINIT, FAIL, "unable to register conversion function"); } + if (H5Tregister_soft ("f_f", H5T_FLOAT, H5T_FLOAT, + H5T_conv_f_f) < 0) { + HRETURN_ERROR (H5E_DATATYPE, H5E_CANTINIT, FAIL, + "unable to register conversion function"); + } if (H5Tregister_soft("ibo", H5T_INTEGER, H5T_INTEGER, H5T_conv_order) < 0) { HRETURN_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL, @@ -597,7 +602,16 @@ H5T_init_interface(void) HRETURN_ERROR (H5E_DATATYPE, H5E_CANTINIT, FAIL, "unable to register conversion function"); } - + if (H5Tregister_hard("flt_dbl", H5T_NATIVE_FLOAT, H5T_NATIVE_DOUBLE, + H5T_conv_float_double)<0) { + HRETURN_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL, + "unable to register conversion function"); + } + if (H5Tregister_hard("dbl_flt", H5T_NATIVE_DOUBLE, H5T_NATIVE_FLOAT, + H5T_conv_double_float)<0) { + HRETURN_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL, + "unable to register conversion function"); + } FUNC_LEAVE(ret_value); } @@ -2879,7 +2893,7 @@ H5Tregister_soft (const char *name, H5T_class_t src_cls, H5T_class_t dst_cls, HRETURN_ERROR (H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed"); } - H5T_asoft_g = na; + H5T_asoft_g = (intn)na; H5T_soft_g = x; } HDstrncpy (H5T_soft_g[H5T_nsoft_g].name, name, H5T_NAMELEN); @@ -3697,7 +3711,7 @@ H5T_insert(H5T_t *parent, const char *name, size_t offset, const H5T_t *member) HRETURN_ERROR (H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed"); } - parent->u.compnd.nalloc = na; + parent->u.compnd.nalloc = (intn)na; parent->u.compnd.memb = x; } @@ -4197,7 +4211,7 @@ H5T_path_find(const char *name, const H5T_t *src, const H5T_t *dst, HRETURN_ERROR (H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed"); } - H5T_apath_g = na; + H5T_apath_g = (intn)na; H5T_path_g = x; } if (cmp > 0) md++; @@ -4266,6 +4280,7 @@ H5T_path_find(const char *name, const H5T_t *src, const H5T_t *dst, } if ((H5T_soft_g[i].func) (src_id, dst_id, &(path->cdata), H5T_CONV_INIT, NULL, NULL) < 0) { + H5MM_xfree(path->cdata.stats); HDmemset (&(path->cdata), 0, sizeof(H5T_cdata_t)); H5E_clear(); /*ignore the error*/ } else { diff --git a/src/H5Tbit.c b/src/H5Tbit.c index b9a830d..d80c8b3 100644 --- a/src/H5Tbit.c +++ b/src/H5Tbit.c @@ -11,8 +11,15 @@ */ #define H5T_PACKAGE #include +#include +#include #include +/* Interface initialization */ +#define PABLO_MASK H5Tbit_mask +static intn interface_initialize_g = FALSE; +#define INTERFACE_INIT NULL + /*------------------------------------------------------------------------- * Function: H5T_bit_copy @@ -40,8 +47,8 @@ H5T_bit_copy (uint8 *dst, size_t dst_offset, const uint8 *src, * Normalize the offset to be a byte number and a bit offset within that * byte. */ - s_idx = src_offset / 8; - d_idx = dst_offset / 8; + s_idx = (intn)src_offset / 8; + d_idx = (intn)dst_offset / 8; src_offset %= 8; dst_offset %= 8; @@ -62,7 +69,7 @@ H5T_bit_copy (uint8 *dst, size_t dst_offset, const uint8 *src, * dst[d_idx+1] dst[d_idx] */ while (src_offset && size>0) { - unsigned nbits = MIN3 (size, 8-dst_offset, 8-src_offset); + unsigned nbits = (unsigned)MIN3 (size, 8-dst_offset, 8-src_offset); unsigned mask = (1<8; size-=8, d_idx++, s_idx++) { if (shift) { @@ -119,7 +126,7 @@ H5T_bit_copy (uint8 *dst, size_t dst_offset, const uint8 *src, /* Finish up */ while (size>0) { - unsigned nbits = MIN3 (size, 8-dst_offset, 8-src_offset); + unsigned nbits = (unsigned)MIN3 (size, 8-dst_offset, 8-src_offset); unsigned mask = (1<=size); + + H5T_bit_copy ((uint8*)&val, 0, buf, offset, size); + switch (((H5T_t*)(H5I_object(H5T_NATIVE_INT_g)))->u.atomic.order) { + case H5T_ORDER_LE: + break; + + case H5T_ORDER_BE: + for (i=0, hs=sizeof(val)/2; i=size); + + switch (((H5T_t*)(H5I_object(H5T_NATIVE_INT_g)))->u.atomic.order) { + case H5T_ORDER_LE: + break; + + case H5T_ORDER_BE: + for (i=0, hs=sizeof(val)/2; i>start) & mask; + acc += 1; + carry = acc & (1<=8) { + acc = buf[idx]; + acc += 1; + carry = acc & 0x100; + buf[idx] = acc & 0xff; + idx++; + size -= 8; + } + + /* The last bits */ + if (carry && size>0) { + mask = (1<size>=dst->size) { sp = dp = (uint8*)buf; direction = 1; - olap = ceil((double)(src->size)/(src->size-dst->size))-1; + olap = (size_t)(ceil((double)(src->size)/ + (double)(src->size-dst->size))-1); } else { sp = (uint8*)buf + (nelmts-1) * src->size; dp = (uint8*)buf + (nelmts-1) * dst->size; direction = -1; - olap = ceil((double)(dst->size)/(dst->size-src->size))-1; + olap = (size_t)(ceil((double)(dst->size)/ + (double)(dst->size-src->size))-1); } /* The conversion loop */ @@ -871,6 +873,497 @@ H5T_conv_i_i (hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata, /*------------------------------------------------------------------------- + * Function: H5T_conv_f_f + * + * Purpose: Convert one floating point type to another. This is a catch + * all for floating point conversions and is probably not + * particularly fast! + * + * Return: Success: SUCCEED + * + * Failure: FAIL + * + * Programmer: Robb Matzke + * Tuesday, June 23, 1998 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +herr_t +H5T_conv_f_f (hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata, + size_t nelmts, void *buf, void __unused__ *bkg) +{ + /* Traversal-related variables */ + H5T_t *src_p; /*source data type */ + H5T_t *dst_p; /*destination data type */ + H5T_atomic_t src; /*atomic source info */ + H5T_atomic_t dst; /*atomic destination info */ + intn direction; /*forward or backward traversal */ + size_t elmtno; /*element number */ + size_t half_size; /*half the type size */ + size_t olap; /*num overlapping elements */ + ssize_t bitno; /*bit number */ + uint8 *s, *sp, *d, *dp; /*source and dest traversal ptrs*/ + uint8 dbuf[64]; /*temp destination buffer */ + + /* Conversion-related variables */ + hssize_t expo; /*exponent */ + hssize_t expo_max; /*maximum possible dst exponent */ + size_t msize; /*useful size of mantissa in src*/ + size_t mpos; /*offset to useful mant is src */ + size_t mrsh; /*amount to right shift mantissa*/ + hbool_t carry; /*carry after rounding mantissa */ + size_t i; /*miscellaneous counters */ + size_t implied; /*destination implied bits */ + + FUNC_ENTER (H5T_conv_f_f, FAIL); + + switch (cdata->command) { + case H5T_CONV_INIT: + if (H5_DATATYPE!=H5I_group (src_id) || + NULL==(src_p=H5I_object (src_id)) || + H5_DATATYPE!=H5I_group (dst_id) || + NULL==(dst_p=H5I_object (dst_id))) { + HRETURN_ERROR (H5E_ARGS, H5E_BADTYPE, FAIL, "not a data type"); + } + src = src_p->u.atomic; + dst = dst_p->u.atomic; + if (H5T_ORDER_LE!=src.order && + H5T_ORDER_BE!=src.order) { + HRETURN_ERROR (H5E_DATATYPE, H5E_UNSUPPORTED, FAIL, + "unsupported byte order"); + } + if (H5T_ORDER_LE!=dst.order && + H5T_ORDER_BE!=dst.order) { + HRETURN_ERROR (H5E_DATATYPE, H5E_UNSUPPORTED, FAIL, + "unsupported byte order"); + } + if (dst_p->size>sizeof(dbuf)) { + HRETURN_ERROR (H5E_DATATYPE, H5E_UNSUPPORTED, FAIL, + "destination size is too large"); + } + if (8*sizeof(expo)-1need_bkg = H5T_BKG_NO; + break; + + case H5T_CONV_FREE: + break; + + case H5T_CONV_CONV: + /* Get the data types */ + if (H5_DATATYPE!=H5I_group (src_id) || + NULL==(src_p=H5I_object (src_id)) || + H5_DATATYPE!=H5I_group (dst_id) || + NULL==(dst_p=H5I_object (dst_id))) { + HRETURN_ERROR (H5E_ARGS, H5E_BADTYPE, FAIL, "not a data type"); + } + src = src_p->u.atomic; + dst = dst_p->u.atomic; + expo_max = ((hssize_t)1 << dst.u.f.esize) - 1; + + /* + * Do we process the values from beginning to end or vice versa? Also, + * how many of the elements have the source and destination areas + * overlapping? + */ + if (src_p->size==dst_p->size) { + sp = dp = (uint8*)buf; + direction = 1; + olap = nelmts; + } else if (src_p->size>=dst_p->size) { + sp = dp = (uint8*)buf; + direction = 1; + olap = (size_t)(ceil((double)(src_p->size)/ + (double)(src_p->size-dst_p->size))-1); + } else { + sp = (uint8*)buf + (nelmts-1) * src_p->size; + dp = (uint8*)buf + (nelmts-1) * dst_p->size; + direction = -1; + olap = (size_t)(ceil((double)(dst_p->size)/ + (double)(dst_p->size-src_p->size))-1); + } + + /* The conversion loop */ + for (elmtno=0; elmtno0) { + s = sp; + d = elmtno= nelmts-olap ? dbuf : dp; + } +#ifndef NDEBUG + /* I don't quite trust the overlap calculations yet --rpm */ + if (d==dbuf) { + assert ((dp>=sp && dpsize) || + (sp>=dp && spsize)); + } else { + assert ((dpsize<=sp) || + (spsize<=dp)); + } +#endif + + /* + * Put the data in little endian order so our loops aren't so + * complicated. We'll do all the conversion stuff assuming + * little endian and then we'll fix the order at the end. + */ + if (H5T_ORDER_BE==src.order) { + half_size = src_p->size/2; + for (i=0; isize-(i+1)]; + s[src_p->size-(i+1)] = s[i]; + s[i] = tmp; + } + } + + /* + * Check for special cases: +0, -0, +Inf, -Inf, NaN + */ + if (H5T_bit_find (s, src.u.f.mpos, src.u.f.msize, + H5T_BIT_LSB, TRUE)<0) { + if (H5T_bit_find (s, src.u.f.epos, src.u.f.esize, + H5T_BIT_LSB, TRUE)<0) { + /* +0 or -0 */ + H5T_bit_copy (d, dst.u.f.sign, s, src.u.f.sign, 1); + H5T_bit_set (d, dst.u.f.epos, dst.u.f.esize, FALSE); + H5T_bit_set (d, dst.u.f.mpos, dst.u.f.esize, FALSE); + goto padding; + } else if (H5T_bit_find (s, src.u.f.epos, src.u.f.esize, + H5T_BIT_LSB, FALSE)<0) { + /* +Inf or -Inf */ + H5T_bit_copy (d, dst.u.f.sign, s, src.u.f.sign, 1); + H5T_bit_set (d, dst.u.f.epos, dst.u.f.esize, TRUE); + H5T_bit_set (d, dst.u.f.mpos, dst.u.f.msize, FALSE); + goto padding; + } + } else if (H5T_bit_find (s, src.u.f.epos, src.u.f.esize, + H5T_BIT_LSB, FALSE)<0) { + /* + * NaN. There are many NaN values, so we just set all bits of + * the significand. + */ + H5T_bit_copy (d, dst.u.f.sign, s, src.u.f.sign, 1); + H5T_bit_set (d, dst.u.f.epos, dst.u.f.esize, TRUE); + H5T_bit_set(d, dst.u.f.mpos, dst.u.f.msize, TRUE); + goto padding; + } + + /* + * Get the exponent as an unsigned quantity from the section of + * the source bit field where it's located. Don't worry about + * the exponent bias yet. + */ + expo = H5T_bit_get_d(s, src.u.f.epos, src.u.f.esize); + + /* + * Set markers for the source mantissa, excluding the leading `1' + * (might be implied). + */ + implied = 1; + mpos = src.u.f.mpos; + mrsh = 0; + if (0==expo || H5T_NORM_NONE==src.u.f.norm) { + if ((bitno=H5T_bit_find(s, src.u.f.mpos, src.u.f.msize, + H5T_BIT_MSB, TRUE))>0) { + msize = bitno; + } else if (0==bitno) { + msize = 1; + H5T_bit_set(s, src.u.f.mpos, 1, FALSE); + } + } else if (H5T_NORM_IMPLIED==src.u.f.norm) { + msize = src.u.f.msize; + } else { + assert("normalization method not implemented yet" && 0); + abort(); + } + + /* + * The sign for the destination is the same as the sign for the + * source in all cases. + */ + H5T_bit_copy (d, dst.u.f.sign, s, src.u.f.sign, 1); + + /* + * Calculate the true source exponent by adjusting according to + * the source exponent bias. + */ + if (0==expo || H5T_NORM_NONE==src.u.f.norm) { + bitno = H5T_bit_find(s, src.u.f.mpos, src.u.f.msize, + H5T_BIT_MSB, TRUE); + assert(bitno>=0); + expo -= (src.u.f.ebias-1) + (src.u.f.msize-bitno); + } else if (H5T_NORM_IMPLIED==src.u.f.norm) { + expo -= src.u.f.ebias; + } else { + assert("normalization method not implemented yet" && 0); + abort(); + } + + /* + * If the destination is not normalized then right shift the + * mantissa by one. + */ + if (H5T_NORM_NONE==dst.u.f.norm) { + mrsh++; + } + + /* + * Calculate the destination exponent by adding the destination + * bias and clipping by the minimum and maximum possible + * destination exponent values. + */ + expo += dst.u.f.ebias; + if (expo < -(hssize_t)(dst.u.f.msize)) { + /* The exponent is way too small. Result is zero. */ + expo = 0; + H5T_bit_set(d, dst.u.f.mpos, dst.u.f.msize, FALSE); + msize = 0; + + } else if (expo<=0) { + /* + * The exponent is too small to fit in the exponent field, + * but by shifting the mantissa to the right we can + * accomodate that value. The mantissa of course is no + * longer normalized. + */ + mrsh += 1-expo; + expo = 0; + + } else if (expo>=expo_max) { + /* + * The exponent is too large to fit in the available region + * or it results in the maximum possible value. Use positive + * or negative infinity instead. + */ + expo = expo_max; + H5T_bit_set(d, dst.u.f.mpos, dst.u.f.msize, FALSE); + msize = 0; + + } + + /* + * If the destination mantissa is smaller than the source + * mantissa then round the source mantissa. Rounding may cause a + * carry in which case the exponent has to be re-evaluated for + * overflow. That is, if `carry' is clear then the implied + * mantissa bit is `1', else it is `10' binary. + */ + if (msize>0 && mrsh<=dst.u.f.msize && mrsh+msize>dst.u.f.msize) { + bitno = (ssize_t)(mrsh+msize - dst.u.f.msize); + assert(bitno>=0 && (size_t)bitno<=msize); + carry = H5T_bit_inc(s, mpos+bitno-1, 1+msize-bitno); + if (carry) implied = 2; + } + + /* + * Write the mantissa to the destination + */ + if (mrsh>dst.u.f.msize+1) { + H5T_bit_set(d, dst.u.f.mpos, dst.u.f.msize, FALSE); + } else if (mrsh==dst.u.f.msize+1) { + H5T_bit_set(d, dst.u.f.mpos+1, dst.u.f.msize-1, FALSE); + H5T_bit_set(d, dst.u.f.mpos, 1, TRUE); + } else if (mrsh==dst.u.f.msize) { + H5T_bit_set(d, dst.u.f.mpos, dst.u.f.msize, FALSE); + H5T_bit_set_d(d, dst.u.f.mpos, MIN(2, dst.u.f.msize), implied); + } else { + if (mrsh>0) { + H5T_bit_set(d, dst.u.f.mpos+dst.u.f.msize-mrsh, mrsh, + FALSE); + H5T_bit_set_d(d, dst.u.f.mpos+dst.u.f.msize-mrsh, 2, + implied); + } + if (mrsh+msize>=dst.u.f.msize) { + H5T_bit_copy(d, dst.u.f.mpos, + s, (mpos+msize+mrsh-dst.u.f.msize), + dst.u.f.msize-mrsh); + } else { + H5T_bit_copy(d, dst.u.f.mpos+dst.u.f.msize-(mrsh+msize), + s, mpos, msize); + H5T_bit_set(d, dst.u.f.mpos, dst.u.f.msize-(mrsh+msize), + FALSE); + } + } + + /* Write the exponent */ + H5T_bit_set_d(d, dst.u.f.epos, dst.u.f.esize, expo); + + padding: +#ifndef LATER + /* + * Set internal padding areas + */ +#endif + + /* + * Set external padding areas + */ + if (dst.offset>0) { + assert (H5T_PAD_ZERO==dst.lsb_pad || + H5T_PAD_ONE==dst.lsb_pad); + H5T_bit_set (d, 0, dst.offset, + H5T_PAD_ONE==dst.lsb_pad); + } + if (dst.offset+dst.prec!=8*dst_p->size) { + assert (H5T_PAD_ZERO==dst.msb_pad || + H5T_PAD_ONE==dst.msb_pad); + H5T_bit_set (d, dst.offset+dst.prec, + 8*dst_p->size - (dst.offset+dst.prec), + H5T_PAD_ONE==dst.msb_pad); + } + + /* + * Put the destination in the correct byte order. See note at + * beginning of loop. + */ + if (H5T_ORDER_BE==dst.order) { + half_size = dst_p->size/2; + for (i=0; isize-(i+1)]; + d[dst_p->size-(i+1)] = d[i]; + d[i] = tmp; + } + } + + /* + * If we had used a temporary buffer for the destination then we + * should copy the value to the true destination buffer. + */ + if (d==dbuf) HDmemcpy (dp, d, dst_p->size); + sp += direction * src_p->size; + dp += direction * dst_p->size; + } + + break; + + default: + HRETURN_ERROR (H5E_DATATYPE, H5E_UNSUPPORTED, FAIL, + "unknown conversion command"); + } + + FUNC_LEAVE (SUCCEED); +} + + +/*------------------------------------------------------------------------- + * Function: H5T_conv_float_double + * + * Purpose: Convert native `float' to native `double' using hardware. + * This is a fast special case. + * + * Return: Success: SUCCEED + * + * Failure: FAIL + * + * Programmer: Robb Matzke + * Tuesday, June 23, 1998 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +herr_t +H5T_conv_float_double (hid_t __unused__ src_id, hid_t __unused__ dst_id, + H5T_cdata_t *cdata, size_t nelmts, void *buf, + void __unused__ *bkg) +{ + size_t elmtno; /*element number */ + float *s; /*source buffer */ + double *d; /*destination buffer */ + + FUNC_ENTER (H5T_conv_float_double, FAIL); + + switch (cdata->command) { + case H5T_CONV_INIT: + cdata->need_bkg = H5T_BKG_NO; + break; + + case H5T_CONV_FREE: + break; + + case H5T_CONV_CONV: + s = (float*)buf + nelmts; + d = (double*)buf + nelmts; + + for (elmtno=0; elmtnocommand) { + case H5T_CONV_INIT: + cdata->need_bkg = H5T_BKG_NO; + break; + + case H5T_CONV_FREE: + break; + + case H5T_CONV_CONV: + s = (double*)buf; + d = (float*)buf; + + for (elmtno=0; elmtno #include #include +#include #include #ifndef HAVE_ATTRIBUTE 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 #include +#include +#include #include #include #include +#define H5T_PACKAGE +#include /*to turn off hardware conversions*/ + #include #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 %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=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"); -- cgit v0.12