/*
 * Copyright (C) 1998 Spizella Software
 *		      All rights reserved.
 *
 * Programmer:	Robb Matzke <robb@arborea.spizella.com>
 *		Tuesday, January 13, 1998
 *
 * Purpose:	Data type conversions.
 */
#define H5T_PACKAGE		/*suppress error about including H5Tpkg	     */

#define PABLO_MASK    H5Tconv_mask
#include <H5Iprivate.h>
#include <H5Eprivate.h>
#include <H5MMprivate.h>
#include <H5Pprivate.h>
#include <H5Tpkg.h>
#include <H5TBprivate.h>

/* Conversion data for H5T_conv_struct() */
typedef struct H5T_conv_struct_t {
    intn	*src2dst;		/*mapping from src to dst member num */
    hid_t	*src_memb_id;		/*source member type ID's	     */
    hid_t	*dst_memb_id;		/*destination member type ID's	     */
    H5T_path_t	**memb_path;		/*conversion path for each member    */
    size_t	*memb_nelmts;		/*member element count		     */
} H5T_conv_struct_t;

/* Conversion data for H5T_conv_enum() */
typedef struct H5T_enum_struct_t {
    intn	base;			/*lowest `in' value		     */
    intn	length;			/*num elements in arrays	     */
    intn	*src2dst;		/*map from src to dst index	     */
} H5T_enum_struct_t;

/* Conversion data for the hardware conversion functions */
typedef struct H5T_conv_hw_t {
    hsize_t	s_aligned;		/*number source elements aligned     */
    hsize_t	d_aligned;		/*number destination elements aligned*/
} H5T_conv_hw_t;

/* Interface initialization */
static intn interface_initialize_g = 0;
#define INTERFACE_INIT NULL

/*
 * These macros are for the bodies of functions that convert buffers of one
 * integer type to another using hardware.  They all start with `H5T_CONV_'
 * and end with two letters that represent the source and destination types,
 * respectively. The letters `s' and `S' refer to signed values while the
 * letters `u' and `U' refer to unsigned values. The letter which is
 * capitalized indicates that the corresponding type (source or destination)
 * is at least as large as the other type.  Certain conversions may
 * experience overflow conditions which arise when the source value has a
 * magnitude that cannot be represented by the destination type.
 *
 * Suffix	Description
 * ------	-----------
 * sS:		Signed integers to signed integers where the destination is
 *		at least as wide as the source.	 This case cannot generate
 *		overflows.
 *
 * sU:		Signed integers to unsigned integers where the destination is
 *		at least as wide as the source.	 This case experiences
 *		overflows when the source value is negative.
 *
 * uS:		Unsigned integers to signed integers where the destination is
 *		at least as wide as the source.	 This case can experience
 *		overflows when the source and destination are the same size.
 *
 * uU:		Unsigned integers to unsigned integers where the destination
 *		is at least as wide as the source.  Overflows are not
 *		possible in this case.
 *
 * Ss:		Signed integers to signed integers where the source is at
 *		least as large as the destination.  Overflows can occur when
 *		the destination is narrower than the source.
 *
 * Su:		Signed integers to unsigned integers where the source is at
 *		least as large as the destination.  Overflows occur when the
 *		source value is negative and can also occur if the
 *		destination is narrower than the source.
 *
 * Us:		Unsigned integers to signed integers where the source is at
 *		least as large as the destination.  Overflows can occur for
 *		all sizes.
 *
 * Uu:		Unsigned integers to unsigned integers where the source is at
 *		least as large as the destination. Overflows can occur if the
 *		destination is narrower than the source.
 *
 * su:		Conversion from signed integers to unsigned integers where
 *		the source and destination are the same size. Overflow occurs
 *		when the source value is negative.
 *
 * us:		Conversion from unsigned integers to signed integers where
 *		the source and destination are the same size.  Overflow
 *		occurs when the source magnitude is too large for the
 *		destination.
 *
 * The macros take a subset of these arguments in the order listed here:
 *
 * CDATA:	A pointer to the H5T_cdata_t structure that was passed to the
 *		conversion function.
 *
 * S_ID:	The hid_t value for the source data type.
 *
 * D_ID:	The hid_t value for the destination data type.
 *
 * BUF:		A pointer to the conversion buffer.
 *
 * NELMTS:	The number of values to be converted.
 *
 * ST:		The C name for source data type (e.g., int)
 *
 * DT:		The C name for the destination data type (e.g., signed char)
 *
 * D_MIN:	The minimum possible destination value.	 For unsigned
 *		destination types this should be zero.	For signed
 *		destination types it's a negative value with a magnitude that
 *		is usually one greater than D_MAX.  Source values which are
 *		smaller than D_MIN generate overflows.
 *
 * D_MAX:	The maximum possible destination value. Source values which
 *		are larger than D_MAX generate overflows.
 * 
 */
#define H5T_CONV_sS(S_ALIGN,D_ALIGN,ST,DT) {				      \
    assert(sizeof(ST)<=sizeof(DT));					      \
    CI_BEGIN(S_ALIGN, D_ALIGN, ST, DT, nelmts-1) {			      \
	*((DT*)d) = (DT)(*((ST*)s));					      \
    } CI_END;								      \
}

#define H5T_CONV_sU(STYPE,DTYPE,ST,DT) {				      \
    assert(sizeof(ST)<=sizeof(DT));					      \
    CI_BEGIN(STYPE, DTYPE, ST, DT, nelmts-1) {				      \
	if (*((ST*)s)<0) {						      \
	    if (!H5T_overflow_g ||					      \
		(H5T_overflow_g)(src_id, dst_id, s, d)<0) {		      \
		*((DT*)d) = 0;						      \
	    }								      \
	} else {							      \
	    *((DT*)d) = (DT)(*((ST*)s));				      \
	}								      \
    } CI_END;								      \
}

#define H5T_CONV_uS(STYPE,DTYPE,ST,DT,D_MAX) {				      \
    assert(sizeof(ST)<=sizeof(DT));					      \
    CI_BEGIN(STYPE, DTYPE, ST, DT, nelmts-1) {				      \
	if (*((ST*)s) > (D_MAX)) {					      \
	    if (!H5T_overflow_g ||					      \
		(H5T_overflow_g)(src_id, dst_id, s, d)<0) {		      \
		*((DT*)d) = (D_MAX);					      \
	    }								      \
	} else {							      \
	    *((DT*)d) = (DT)(*((ST*)s));				      \
	}								      \
    } CI_END;								      \
}

#define H5T_CONV_uU(STYPE,DTYPE,ST,DT) {				      \
    assert(sizeof(ST)<=sizeof(DT));					      \
    CI_BEGIN(STYPE, DTYPE, ST, DT, nelmts-1) {				      \
	*((DT*)d) = (DT)(*((ST*)s));					      \
    } CI_END;								      \
}

#define H5T_CONV_Ss(STYPE,DTYPE,ST,DT,D_MIN,D_MAX) {			      \
    assert(sizeof(ST)>=sizeof(DT));					      \
    CI_BEGIN(STYPE, DTYPE, ST, DT, 0) {					      \
	if (*((ST*)s) > (DT)(D_MAX)) {					      \
	    if (!H5T_overflow_g ||					      \
		(H5T_overflow_g)(src_id, dst_id, s, d)<0) {		      \
		*((DT*)d) = (D_MAX);					      \
	    }								      \
	} else if (*((ST*)s) < (D_MIN)) {				      \
	    if (!H5T_overflow_g ||					      \
		(H5T_overflow_g)(src_id, dst_id, s, d)<0) {		      \
		*((DT*)d) = (D_MIN);					      \
	    }								      \
	} else {							      \
	    *((DT*)d) = (DT)(*((ST*)s));				      \
	}								      \
    } CI_END;								      \
}

#define H5T_CONV_Su(STYPE,DTYPE,ST,DT,D_MAX) {				      \
    assert(sizeof(ST)>=sizeof(DT));					      \
    CI_BEGIN(STYPE, DTYPE, ST, DT, 0) {					      \
	if (*((ST*)s) < 0) {						      \
	    if (!H5T_overflow_g ||					      \
		(H5T_overflow_g)(src_id, dst_id, s, d)<0) {		      \
		*((DT*)d) = 0;						      \
	    }								      \
	} else if (sizeof(ST)>sizeof(DT) && *((ST*)s)>(ST)(D_MAX)) {	      \
	    /*sign vs. unsign ok in previous line*/			      \
	    if (!H5T_overflow_g ||					      \
		(H5T_overflow_g)(src_id, dst_id, s, d)<0) {		      \
		*((DT*)d) = (D_MAX);					      \
	    }								      \
	} else {							      \
	    *((DT*)d) = (DT)(*((ST*)s));				      \
	}								      \
    } CI_END;								      \
}

#define H5T_CONV_Us(STYPE,DTYPE,ST,DT,D_MAX) {				      \
    assert(sizeof(ST)>=sizeof(DT));					      \
    CI_BEGIN(STYPE, DTYPE, ST, DT, 0) {					      \
	if (*((ST*)s) > (D_MAX)) {					      \
	    if (!H5T_overflow_g ||					      \
		(H5T_overflow_g)(src_id, dst_id, s, d)<0) {		      \
		*((DT*)d) = (D_MAX);					      \
	    }								      \
	} else {							      \
	    *((DT*)d) = (DT)(*((ST*)s));				      \
	}								      \
    } CI_END;								      \
}

#define H5T_CONV_Uu(STYPE,DTYPE,ST,DT,D_MAX) {				      \
    assert(sizeof(ST)>=sizeof(DT));					      \
    CI_BEGIN(STYPE, DTYPE, ST, DT, 0) {					      \
	if (*((ST*)s) > (D_MAX)) {					      \
	    if (!H5T_overflow_g ||					      \
		(H5T_overflow_g)(src_id, dst_id, s, d)<0) {		      \
		*((DT*)d) = (D_MAX);					      \
	    }								      \
	} else {							      \
	    *((DT*)d) = (DT)(*((ST*)s));				      \
	}								      \
    } CI_END;								      \
}

#define H5T_CONV_su(STYPE,DTYPE,ST,DT) {				      \
    assert(sizeof(ST)==sizeof(DT));					      \
    CI_BEGIN(STYPE, DTYPE, ST, DT, 0) {					      \
	if (*((ST*)s) < 0) {						      \
	    if (!H5T_overflow_g ||					      \
		(H5T_overflow_g)(src_id, dst_id, s, d)<0) {		      \
		*((DT*)d) = 0;						      \
	    }								      \
	} else {							      \
	    *((DT*)d) = (DT)(*((ST*)s));				      \
	}								      \
    } CI_END;								      \
}

#define H5T_CONV_us(STYPE,DTYPE,ST,DT,D_MAX) {				      \
    assert(sizeof(ST)==sizeof(DT));					      \
    CI_BEGIN(STYPE, DTYPE, ST, DT, 0) {					      \
	if (*((ST*)s) > (D_MAX)) {					      \
	    if (!H5T_overflow_g ||					      \
		(H5T_overflow_g)(src_id, dst_id, s, d)<0) {		      \
		*((DT*)d) = (D_MAX);					      \
	    }								      \
	} else {							      \
	    *((DT*)d) = (DT)(*((ST*)s));				      \
	}								      \
    } CI_END;								      \
}

/* The first part of every integer hardware conversion macro */
#define CI_BEGIN(STYPE,DTYPE,ST,DT,STRT) {				      \
    size_t	elmtno;			/*element number		*/    \
    uint8_t	*src, *s;		/*source buffer			*/    \
    uint8_t	*dst, *d;		/*destination buffer		*/    \
    H5T_t	*st, *dt;		/*data type descriptors		*/    \
    long_long	aligned;		/*largest integer type, aligned	*/    \
    hbool_t	s_mv, d_mv;		/*move data to align it?	*/    \
    size_t      dt_size=sizeof(DT);	/*needed by CI_END macro	*/    \
    H5T_conv_hw_t *priv = cdata->priv;	/*private data			*/    \
    size_t	s_stride, d_stride;	/*src and dst strides		*/    \
    int		direction;		/*1=left-to-right, -1=rt-to-lt	*/    \
									      \
    switch (cdata->command) {						      \
    case H5T_CONV_INIT:							      \
	/* Sanity check and initialize statistics */			      \
	cdata->need_bkg = H5T_BKG_NO;					      \
	if (NULL==(st=H5I_object(src_id)) ||				      \
	    NULL==(dt=H5I_object(dst_id))) {				      \
	    HRETURN_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL,		      \
			  "unable to dereference data type object ID");	      \
	}								      \
	if (st->size!=sizeof(ST) || dt->size!=sizeof(DT)) {		      \
	    HRETURN_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL,		      \
			  "disagreement about data type size");		      \
	}								      \
	if (NULL==(cdata->priv=H5MM_calloc(sizeof(H5T_conv_hw_t)))) {	      \
	    HRETURN_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL,		      \
			  "memory allocation failed");			      \
	}								      \
	break;								      \
									      \
    case H5T_CONV_FREE:							      \
	/* Print and free statistics */					      \
	CI_PRINT_STATS(STYPE,DTYPE);					      \
	cdata->priv = H5MM_xfree(cdata->priv);				      \
	break;								      \
									      \
    case H5T_CONV_CONV:							      \
	/* Initialize pointers */					      \
	if (stride) {							      \
	    s_stride = d_stride = stride;				      \
	    src = dst = buf;						      \
	    direction = 1;						      \
	} else if (STRT) {						      \
	    s_stride = sizeof(ST);					      \
	    d_stride = sizeof(DT);					      \
	    src = (uint8_t*)buf+(STRT)*s_stride;			      \
	    dst = (uint8_t*)buf+(STRT)*d_stride;			      \
            direction = -1;						      \
	} else {							      \
	    s_stride = sizeof(ST);					      \
	    d_stride = sizeof(DT);					      \
            src = dst = buf;						      \
            direction = 1;						      \
        }								      \
									      \
	/* Is alignment required for source or dest? */			      \
	s_mv = H5T_NATIVE_##STYPE##_ALIGN_g>1 &&			      \
               ((size_t)buf%H5T_NATIVE_##STYPE##_ALIGN_g ||		      \
		s_stride%H5T_NATIVE_##STYPE##_ALIGN_g);			      \
	d_mv = H5T_NATIVE_##DTYPE##_ALIGN_g>1 &&			      \
               ((size_t)buf%H5T_NATIVE_##DTYPE##_ALIGN_g ||		      \
                d_stride%H5T_NATIVE_##DTYPE##_ALIGN_g);			      \
	if (s_mv) priv->s_aligned += nelmts;				      \
	if (d_mv) priv->d_aligned += nelmts;				      \
									      \
	for (elmtno=0; elmtno<nelmts; elmtno++) {			      \
	    /* Alignment */						      \
	    if (s_mv) {							      \
		HDmemcpy(&aligned, src, sizeof(ST));			      \
		s = (uint8_t*)&aligned;					      \
	    } else {							      \
		s = src;						      \
	    }								      \
	    if (d_mv) {							      \
		d = (uint8_t*)&aligned;					      \
	    } else {							      \
		d = dst;						      \
	    }								      \
	    /* ... user-defined stuff here -- the conversion ... */
#define CI_END								      \
	    /* Copy destination to final location */			      \
            if (d_mv) HDmemcpy(dst, &aligned, dt_size);			      \
									      \
	    /* Advance pointers */					      \
	    src += direction * s_stride;				      \
	    dst += direction * d_stride;				      \
        }								      \
        break;								      \
									      \
    default:								      \
	HRETURN_ERROR(H5E_DATATYPE, H5E_UNSUPPORTED, FAIL,		      \
		      "unknown conversion command");			      \
    }									      \
}

/* Print alignment statistics */
#ifdef H5T_DEBUG
#   define CI_PRINT_STATS(STYPE,DTYPE) {				      \
    if (H5DEBUG(T) && priv->s_aligned) {				      \
	HDfprintf(H5DEBUG(T),						      \
		  "      %Hu src elements aligned on %lu-byte boundaries\n",  \
		  priv->s_aligned,					      \
		  (unsigned long)H5T_NATIVE_##STYPE##_ALIGN_g);		      \
    }									      \
    if (H5DEBUG(T) && priv->d_aligned) {				      \
	HDfprintf(H5DEBUG(T),						      \
		  "      %Hu dst elements aligned on %lu-byte boundaries\n",  \
		  priv->d_aligned,					      \
		  (unsigned long)H5T_NATIVE_##DTYPE##_ALIGN_g);		      \
    }									      \
}
#else
#   define CI_PRINT_STATS(STYPE,DTYPE) /*void*/
#endif

/*-------------------------------------------------------------------------
 * Function:	H5T_conv_noop
 *
 * Purpose:	The no-op conversion.  The library knows about this
 *		conversion without it being registered.
 *
 * Return: 	Non-negative on success/Negative on failure
 *
 * Programmer:	Robb Matzke
 *		Wednesday, January 14, 1998
 *
 * Modifications:
 *
 *-------------------------------------------------------------------------
 */
herr_t
H5T_conv_noop(hid_t UNUSED src_id, hid_t UNUSED dst_id, H5T_cdata_t *cdata,
	      size_t UNUSED nelmts, size_t UNUSED stride, void UNUSED *buf,
	      void UNUSED *background, hid_t UNUSED dset_xfer_plist)
{
    FUNC_ENTER(H5T_conv_noop, FAIL);

    switch (cdata->command) {
    case H5T_CONV_INIT:
	cdata->need_bkg = H5T_BKG_NO;
	break;

    case H5T_CONV_CONV:
	/* Nothing to convert */
	break;

    case H5T_CONV_FREE:
	break;
	
    default:
	HRETURN_ERROR (H5E_DATATYPE, H5E_UNSUPPORTED, FAIL,
		       "unknown conversion command");
    }

    FUNC_LEAVE(SUCCEED);
}

/*-------------------------------------------------------------------------
 * Function:	H5T_conv_order
 *
 * Purpose:	Convert one type to another when byte order is the only
 *		difference.
 *
 * Note:	This is a soft conversion function.
 *
 * Return:	Non-negative on success/Negative on failure
 *
 * Programmer:	Robb Matzke
 *		Tuesday, January 13, 1998
 *
 * Modifications:
 *		Robb Matzke, 1999-06-16
 *		Added the `stride' argument. If its value is non-zero then we
 *		stride through memory converting one value at each location;
 *		otherwise we assume that the values should be packed.
 *
 * 		Robb Matzke, 1999-06-16
 *		Added support for bitfields.
 *-------------------------------------------------------------------------
 */
herr_t
H5T_conv_order(hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata, size_t nelmts,
	       size_t stride, void *_buf, void UNUSED *background, hid_t UNUSED dset_xfer_plist)
{
    uint8_t	*buf = (uint8_t*)_buf;
    uint8_t	tmp;
    H5T_t	*src = NULL;
    H5T_t	*dst = NULL;
    size_t	i, j, md;

    FUNC_ENTER(H5T_conv_order, FAIL);

    switch (cdata->command) {
    case H5T_CONV_INIT:
	/* Capability query */
	if (H5I_DATATYPE != H5I_get_type(src_id) ||
	    NULL == (src = H5I_object(src_id)) ||
	    H5I_DATATYPE != H5I_get_type(dst_id) ||
	    NULL == (dst = H5I_object(dst_id))) {
	    HRETURN_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a data type");
	}
	if (src->size != dst->size ||
	    0 != src->u.atomic.offset ||
	    0 != dst->u.atomic.offset ||
	    !((H5T_ORDER_BE == src->u.atomic.order &&
	       H5T_ORDER_LE == dst->u.atomic.order) ||
	      (H5T_ORDER_LE == src->u.atomic.order &&
	       H5T_ORDER_BE == dst->u.atomic.order))) {
	    HRETURN_ERROR(H5E_DATATYPE, H5E_UNSUPPORTED, FAIL,
			  "conversion not supported");
	}
	switch (src->type) {
	case H5T_INTEGER:
	case H5T_BITFIELD:
	    /* nothing to check */
	    break;

	case H5T_FLOAT:
	    if (src->u.atomic.u.f.sign != dst->u.atomic.u.f.sign ||
		src->u.atomic.u.f.epos != dst->u.atomic.u.f.epos ||
		src->u.atomic.u.f.esize != dst->u.atomic.u.f.esize ||
		src->u.atomic.u.f.ebias != dst->u.atomic.u.f.ebias ||
		src->u.atomic.u.f.mpos != dst->u.atomic.u.f.mpos ||
		src->u.atomic.u.f.msize != dst->u.atomic.u.f.msize ||
		src->u.atomic.u.f.norm != dst->u.atomic.u.f.norm ||
		src->u.atomic.u.f.pad != dst->u.atomic.u.f.pad) {
		HRETURN_ERROR(H5E_DATATYPE, H5E_UNSUPPORTED, FAIL,
			      "conversion not supported");
	    }
	    break;

	default:
	    HRETURN_ERROR(H5E_DATATYPE, H5E_UNSUPPORTED, FAIL,
			  "conversion not supported");
	}
	cdata->need_bkg = H5T_BKG_NO;
	break;

    case H5T_CONV_CONV:
	/* The conversion */
	if (H5I_DATATYPE != H5I_get_type(src_id) ||
	    NULL == (src = H5I_object(src_id)) ||
	    H5I_DATATYPE != H5I_get_type(dst_id) ||
	    NULL == (dst = H5I_object(dst_id))) {
	    HRETURN_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a data type");
	}
	md = src->size / 2;
	for (i=0; i<nelmts; i++, buf+=stride?stride:src->size) {
	    for (j=0; j<md; j++) {
		tmp = buf[j];
		buf[j] = buf[src->size-(j+1)];
		buf[src->size-(j+1)] = tmp;
	    }
	}
	break;

    case H5T_CONV_FREE:
	/* Free private data */
	break;

    default:
	HRETURN_ERROR (H5E_DATATYPE, H5E_UNSUPPORTED, FAIL,
		       "unknown conversion command");
    }

    FUNC_LEAVE(SUCCEED);
}

/*-------------------------------------------------------------------------
 * Function:	H5T_conv_b_b
 *
 * Purpose:	Convert from one bitfield to any other bitfield.
 *
 * Return:	Non-negative on success/Negative on failure
 *
 * Programmer:	Robb Matzke
 *		Thursday, May 20, 1999
 *
 * Modifications:
 *		Robb Matzke, 1999-06-16
 *		Added support for non-zero strides. If STRIDE is non-zero
 *		then convert one value at each memory location advancing
 *		STRIDE bytes each time; otherwise assume both source and
 *		destination values are packed.
 *-------------------------------------------------------------------------
 */
herr_t
H5T_conv_b_b(hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata, size_t nelmts,
	     size_t stride, void *_buf, void UNUSED *background, hid_t UNUSED dset_xfer_plist)
{
    uint8_t	*buf = (uint8_t*)_buf;
    H5T_t	*src=NULL, *dst=NULL;	/*source and dest data types	*/
    intn	direction;		/*direction of traversal	*/
    size_t	elmtno;			/*element number		*/
    size_t	olap;			/*num overlapping elements	*/
    size_t	half_size;		/*1/2 of total size for swapping*/
    uint8_t	*s, *sp, *d, *dp;	/*source and dest traversal ptrs*/
    uint8_t	dbuf[256];		/*temp destination buffer	*/
    size_t	msb_pad_offset;		/*offset for dest MSB padding	*/
    size_t	i;

    FUNC_ENTER(H5T_conv_b_b, FAIL);

    switch(cdata->command) {
    case H5T_CONV_INIT:
	/* Capability query */
	if (H5I_DATATYPE != H5I_get_type(src_id) ||
	    NULL == (src = H5I_object(src_id)) ||
	    H5I_DATATYPE != H5I_get_type(dst_id) ||
	    NULL == (dst = H5I_object(dst_id))) {
	    HRETURN_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a data type");
	}
	if (H5T_ORDER_LE!=src->u.atomic.order &&
	    H5T_ORDER_BE!=src->u.atomic.order) {
	    HRETURN_ERROR (H5E_DATATYPE, H5E_UNSUPPORTED, FAIL,
			   "unsupported byte order");
	}
	if (H5T_ORDER_LE!=dst->u.atomic.order &&
	    H5T_ORDER_BE!=dst->u.atomic.order) {
	    HRETURN_ERROR (H5E_DATATYPE, H5E_UNSUPPORTED, FAIL,
			   "unsupported byte order");
	}
	cdata->need_bkg = H5T_BKG_NO;
	break;

    case H5T_CONV_FREE:
	break;

    case H5T_CONV_CONV:
	/* Get the data types */
	if (H5I_DATATYPE!=H5I_get_type (src_id) ||
	    NULL==(src=H5I_object (src_id)) ||
	    H5I_DATATYPE!=H5I_get_type (dst_id) ||
	    NULL==(dst=H5I_object (dst_id))) {
	    HRETURN_ERROR (H5E_ARGS, H5E_BADTYPE, FAIL, "not a data type");
	}

	/*
	 * 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->size==dst->size || stride) {
	    sp = dp = (uint8_t*)buf;
	    direction = 1;
	    olap = nelmts;
	} else if (src->size>=dst->size) {
	    double olap_d = HDceil((double)(dst->size)/
				   (double)(src->size-dst->size));
	    
	    olap = (size_t)olap_d;
	    sp = dp = (uint8_t*)buf;
	    direction = 1;
	} else {
	    double olap_d = HDceil((double)(src->size)/
				   (double)(dst->size-src->size));
	    olap = (size_t)olap_d;
	    sp = (uint8_t*)buf + (nelmts-1) * src->size;
	    dp = (uint8_t*)buf + (nelmts-1) * dst->size;
	    direction = -1;
	}

	/* The conversion loop */
	for (elmtno=0; elmtno<nelmts; elmtno++) {

	    /*
	     * If the source and destination buffers overlap then use a
	     * temporary buffer for the destination.
	     */
	    if (direction>0) {
		s = sp;
		d = elmtno<olap ? dbuf : dp;
	    } else {
		s = sp;
		d = elmtno+olap >= nelmts ? dbuf : dp;
	    }
#ifndef NDEBUG
	    /* I don't quite trust the overlap calculations yet --rpm */
	    if (d==dbuf) {
		assert ((dp>=sp && dp<sp+src->size) ||
			(sp>=dp && sp<dp+dst->size));
	    } else {
		assert ((dp<sp && dp+dst->size<=sp) ||
			(sp<dp && sp+src->size<=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->u.atomic.order) {
		half_size = src->size/2;
		for (i=0; i<half_size; i++) {
		    uint8_t tmp = s[src->size-(i+1)];
		    s[src->size-(i+1)] = s[i];
		    s[i] = tmp;
		}
	    }

	    /*
             * Copy the significant part of the value. If the source is larger
             * than the destination then invoke the overflow function or copy
             * as many bits as possible. Zero extra bits in the destination.
             */
	    if (src->u.atomic.prec>dst->u.atomic.prec) {
		if (!H5T_overflow_g ||
		    (H5T_overflow_g)(src_id, dst_id, s, d)<0) {
		    H5T_bit_copy(d, dst->u.atomic.offset,
				 s, src->u.atomic.offset, dst->u.atomic.prec);
		}
	    } else {
		H5T_bit_copy(d, dst->u.atomic.offset,
			     s, src->u.atomic.offset,
			     src->u.atomic.prec);
		H5T_bit_set(d, dst->u.atomic.offset+src->u.atomic.prec,
			    dst->u.atomic.prec-src->u.atomic.prec, FALSE);
	    }

	    /*
             * Fill the destination padding areas.
             */
	    switch (dst->u.atomic.lsb_pad) {
	    case H5T_PAD_ZERO:
		H5T_bit_set(d, 0, dst->u.atomic.offset, FALSE);
		break;
	    case H5T_PAD_ONE:
		H5T_bit_set(d, 0, dst->u.atomic.offset, TRUE);
		break;
	    default:
		HRETURN_ERROR(H5E_DATATYPE, H5E_UNSUPPORTED, FAIL,
			      "unsupported LSB padding");
	    }
	    msb_pad_offset = dst->u.atomic.offset + dst->u.atomic.prec;
	    switch (dst->u.atomic.msb_pad) {
	    case H5T_PAD_ZERO:
		H5T_bit_set(d, msb_pad_offset, 8*dst->size-msb_pad_offset,
			    FALSE);
		break;
	    case H5T_PAD_ONE:
		H5T_bit_set(d, msb_pad_offset, 8*dst->size-msb_pad_offset,
			    TRUE);
		break;
	    default:
		HRETURN_ERROR(H5E_DATATYPE, H5E_UNSUPPORTED, FAIL,
			      "unsupported MSB padding");
	    }

	    /*
	     * Put the destination in the correct byte order.  See note at
	     * beginning of loop.
	     */
	    if (H5T_ORDER_BE==dst->u.atomic.order) {
		half_size = dst->size/2;
		for (i=0; i<half_size; i++) {
		    uint8_t tmp = d[dst->size-(i+1)];
		    d[dst->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->size);
	    if (stride) {
		sp += direction * stride;
		dp += direction * stride;
	    } else {
		sp += direction * src->size;
		dp += direction * dst->size;
	    }
	}
	
	break;

    default:
	HRETURN_ERROR (H5E_DATATYPE, H5E_UNSUPPORTED, FAIL,
		       "unknown conversion command");
    }

    FUNC_LEAVE (SUCCEED);
}
	    
/*-------------------------------------------------------------------------
 * Function:	H5T_conv_struct_init
 *
 * Purpose:	Initialize the `priv' field of `cdata' with conversion
 *		information that is relatively constant.  If `priv' is
 *		already initialized then the member conversion functions
 *		are recalculated.
 *
 *		Priv fields are indexed by source member number or
 *		destination member number depending on whether the field
 *		contains information about the source data type or the
 *		destination data type (fields that contains the same
 *		information for both source and destination are indexed by
 *		source member number).  The src2dst[] priv array maps source
 *		member numbers to destination member numbers, but if the
 *		source member doesn't have a corresponding destination member
 *		then the src2dst[i]=-1.
 *
 * Return:	Non-negative on success/Negative on failure
 *
 * Programmer:	Robb Matzke
 *		Monday, January 26, 1998
 *
 * Modifications:
 *
 *-------------------------------------------------------------------------
 */
static herr_t
H5T_conv_struct_init (H5T_t *src, H5T_t *dst, H5T_cdata_t *cdata)
{
    H5T_conv_struct_t	*priv = (H5T_conv_struct_t*)(cdata->priv);
    intn		i, j, *src2dst = NULL;
    H5T_t		*type = NULL;
    hid_t		tid;
    
    FUNC_ENTER (H5T_conv_struct_init, FAIL);
    
    if (!priv) {
	/*
	 * Allocate private data structure and arrays.
	 */
	if (NULL==(priv=cdata->priv=H5MM_calloc(sizeof(H5T_conv_struct_t))) ||
	    NULL==(priv->src2dst=H5MM_malloc(src->u.compnd.nmembs *
					     sizeof(intn))) ||
	    NULL==(priv->src_memb_id=H5MM_malloc(src->u.compnd.nmembs *
		         			sizeof(hid_t))) ||
	    NULL==(priv->dst_memb_id=H5MM_malloc(dst->u.compnd.nmembs *
		         			sizeof(hid_t))) ||
	    NULL==(priv->memb_nelmts=H5MM_malloc(src->u.compnd.nmembs *
						 sizeof(size_t)))) {
	    HRETURN_ERROR (H5E_RESOURCE, H5E_NOSPACE, FAIL,
			   "memory allocation failed");
	}
	src2dst = priv->src2dst;

	/*
	 * Insure that members are sorted.
	 */
	H5T_sort_value(src, NULL);
	H5T_sort_value(dst, NULL);

	/*
	 * Build a mapping from source member number to destination member
	 * number. If some source member is not a destination member then that
	 * mapping element will be negative.  Also create atoms for each
	 * source and destination member data type so we can look up the
	 * member data type conversion functions later.
	 */
	for (i=0; i<src->u.compnd.nmembs; i++) {
	    src2dst[i] = -1;
	    for (j=0; j<dst->u.compnd.nmembs; j++) {
		if (!HDstrcmp (src->u.compnd.memb[i].name,
			       dst->u.compnd.memb[j].name)) {
		    src2dst[i] = j;
		    break;
		}
	    }
	    if (src2dst[i]>=0) {
		type = H5T_copy (src->u.compnd.memb[i].type, H5T_COPY_ALL);
		tid = H5I_register (H5I_DATATYPE, type);
		assert (tid>=0);
		priv->src_memb_id[i] = tid;

		type = H5T_copy (dst->u.compnd.memb[src2dst[i]].type,
				 H5T_COPY_ALL);
		tid = H5I_register (H5I_DATATYPE, type);
		assert (tid>=0);
		priv->dst_memb_id[src2dst[i]] = tid;
	    }
	}

	/*
	 * Those members which are in both the source and destination must be
	 * the same size and shape arrays.
	 */
	for (i=0; i<src->u.compnd.nmembs; i++) {
	    if (src2dst[i]>=0) {
		H5T_cmemb_t *src_memb = src->u.compnd.memb + i;
		H5T_cmemb_t *dst_memb = dst->u.compnd.memb + src2dst[i];
		if (src_memb->ndims != dst_memb->ndims) {
		    HRETURN_ERROR(H5E_DATATYPE, H5E_UNSUPPORTED, FAIL,
				  "source and dest members have incompatible "
				  "size or shape");
		}
		for (j=0; j<src_memb->ndims; j++) {
		    if (src_memb->dim[j] != dst_memb->dim[j]) {
			HRETURN_ERROR(H5E_DATATYPE, H5E_UNSUPPORTED, FAIL,
				      "source and dest members have "
				      "incompatible size or shape");
		    }
#ifndef LATER
		    /* Their permutation vectors must be equal */
		    if (src_memb->perm[j]!=dst_memb->perm[j]) {
			HRETURN_ERROR(H5E_DATATYPE, H5E_UNSUPPORTED, FAIL,
				      "member permutations must be equal");
		    }
#endif
		}
	    }
	}

	/* Calculate number of elements of each member */
	for (i=0; i<src->u.compnd.nmembs; i++) {
	    priv->memb_nelmts[i] = 1;
	    for (j=0; j<src->u.compnd.memb[i].ndims; j++) {
		priv->memb_nelmts[i] *= src->u.compnd.memb[i].dim[j];
	    }
	}
    }

    /*
     * (Re)build the cache of member conversion functions and pointers to
     * their cdata entries.
     */
    src2dst = priv->src2dst;
    H5MM_xfree(priv->memb_path);
    if (NULL==(priv->memb_path=H5MM_malloc(src->u.compnd.nmembs *
					   sizeof(H5T_path_t*)))) {
	HRETURN_ERROR (H5E_RESOURCE, H5E_NOSPACE, FAIL,
		       "memory allocation failed");
    }

    for (i=0; i<src->u.compnd.nmembs; i++) {
	if (src2dst[i]>=0) {
	    H5T_path_t *tpath;
	    tpath = H5T_path_find(src->u.compnd.memb[i].type,
				  dst->u.compnd.memb[src2dst[i]].type,
				  NULL, NULL);
	    if (NULL==(priv->memb_path[i] = tpath)) {
		H5MM_xfree(priv->src2dst);
		H5MM_xfree(priv->src_memb_id);
		H5MM_xfree(priv->dst_memb_id);
		H5MM_xfree(priv->memb_path);
		H5MM_xfree(priv->memb_nelmts);
		cdata->priv = priv = H5MM_xfree (priv);
		HRETURN_ERROR (H5E_DATATYPE, H5E_UNSUPPORTED, FAIL,
			       "unable to convert member data type");
	    }
	}
    }

    cdata->need_bkg = H5T_BKG_TEMP;
    cdata->recalc = FALSE;
    FUNC_LEAVE (SUCCEED);
}

/*------------------------------------------------------------------------- 
 * Function:	H5T_conv_struct
 *
 * Purpose:	Converts between compound data types.  This is a soft
 *		conversion function.  The algorithm is basically:
 *
 * 		For each element do
 *		  For I=1..NELMTS do
 *		    If sizeof detination type <= sizeof source type then
 *		      Convert member to destination type;
 *		    Move member as far left as possible;
 *		  
 *		  For I=NELMTS..1 do
 *		    If not destination type then
 *		      Convert member to destination type;
 *		    Move member to correct position in BKG
 *
 *		  Copy BKG to BUF
 *
 * Return:	Non-negative on success/Negative on failure
 *
 * Programmer:	Robb Matzke
 *		Thursday, January 22, 1998
 *
 * Modifications:
 *		Robb Matzke, 1999-06-16
 *		Added support for non-zero strides. If STRIDE is non-zero
 *		then convert one value at each memory location advancing
 *		STRIDE bytes each time; otherwise assume both source and
 *		destination values are packed.
 *-------------------------------------------------------------------------
 */
herr_t
H5T_conv_struct(hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata, size_t nelmts,
		size_t stride, void *_buf, void *_bkg, hid_t dset_xfer_plist)
{
    uint8_t	*buf = (uint8_t *)_buf;	/*cast for pointer arithmetic	*/
    uint8_t	*bkg = (uint8_t *)_bkg;	/*background pointer arithmetic	*/
    H5T_t	*src = NULL;		/*source data type		*/
    H5T_t	*dst = NULL;		/*destination data type		*/
    intn	*src2dst = NULL;	/*maps src member to dst member	*/
    H5T_cmemb_t	*src_memb = NULL;	/*source struct member descript.*/
    H5T_cmemb_t	*dst_memb = NULL;	/*destination struct memb desc.	*/
    size_t	offset;			/*byte offset wrt struct	*/
    size_t	src_delta, dst_delta;	/*source & destination stride	*/
    uintn	elmtno;
    intn	i;			/*counters			*/
    H5T_conv_struct_t *priv = (H5T_conv_struct_t *)(cdata->priv);

    FUNC_ENTER (H5T_conv_struct, FAIL);

    switch (cdata->command) {
    case H5T_CONV_INIT:
	/*
	 * First, determine if this conversion function applies to the
	 * conversion path SRC_ID-->DST_ID.  If not, return failure;
	 * otherwise initialize the `priv' field of `cdata' with information
	 * that remains (almost) constant for this conversion path.
	 */
	if (H5I_DATATYPE != H5I_get_type(src_id) ||
	    NULL == (src = H5I_object(src_id)) ||
	    H5I_DATATYPE != H5I_get_type(dst_id) ||
	    NULL == (dst = H5I_object(dst_id))) {
	    HRETURN_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a data type");
	}
	assert (H5T_COMPOUND==src->type);
	assert (H5T_COMPOUND==dst->type);

	if (H5T_conv_struct_init (src, dst, cdata)<0) {
	    HRETURN_ERROR (H5E_DATATYPE, H5E_CANTINIT, FAIL,
			   "unable to initialize conversion data");
	}
	break;

    case H5T_CONV_FREE:
	/*
	 * Free the private conversion data.
	 */
	H5MM_xfree(priv->src2dst);
	H5MM_xfree(priv->src_memb_id);
	H5MM_xfree(priv->dst_memb_id);
	H5MM_xfree(priv->memb_path);
	H5MM_xfree(priv->memb_nelmts);
	cdata->priv = priv = H5MM_xfree (priv);
	break;

    case H5T_CONV_CONV:
	/*
	 * Conversion.
	 */
	if (H5I_DATATYPE != H5I_get_type(src_id) ||
	    NULL == (src = H5I_object(src_id)) ||
	    H5I_DATATYPE != H5I_get_type(dst_id) ||
	    NULL == (dst = H5I_object(dst_id))) {
	    HRETURN_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a data type");
	}
	assert (priv);
	assert (bkg && cdata->need_bkg>=H5T_BKG_TEMP);

	if (cdata->recalc &&
	    H5T_conv_struct_init (src, dst, cdata)<0) {
	    HRETURN_ERROR (H5E_DATATYPE, H5E_CANTINIT, FAIL,
			   "unable to initialize conversion data");
	}

	/*
	 * Insure that members are sorted.
	 */
	H5T_sort_value(src, NULL);
	H5T_sort_value(dst, NULL);
	src2dst = priv->src2dst;

	/*
	 * Direction of conversion.
	 */
	if (stride) {
	    src_delta = dst_delta = stride;
	} else if (dst->size <= src->size) {
	    src_delta = src->size;
	    dst_delta = dst->size;
	} else {
	    src_delta = -(src->size);
	    dst_delta = -(dst->size);
	    buf += (nelmts-1) * src->size;
	    bkg += (nelmts-1) * dst->size;
	}

	for (elmtno=0; elmtno<nelmts; elmtno++) {
	    /*
	     * For each source member which will be present in the
	     * destination, convert the member to the destination type unless
	     * it is larger than the source type.  Then move the member to the
	     * left-most unoccupied position in the buffer.  This makes the
	     * data point as small as possible with all the free space on the
	     * right side.
	     */
	    for (i=0, offset=0; i<src->u.compnd.nmembs; i++) {
		if (src2dst[i]<0) continue;
		src_memb = src->u.compnd.memb + i;
		dst_memb = dst->u.compnd.memb + src2dst[i];

		if (dst_memb->size <= src_memb->size) {
		    if (H5T_convert(priv->memb_path[i],
				    priv->src_memb_id[i],
				    priv->dst_memb_id[src2dst[i]],
				    priv->memb_nelmts[i],
				    0, /*no striding*/
				    buf + src_memb->offset,
				    bkg + dst_memb->offset,dset_xfer_plist)<0) {
			HRETURN_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL,
				      "unable to convert compound data type "
				      "member");
		    }
		    HDmemmove (buf+offset, buf+src_memb->offset,
			       dst_memb->size);
		    offset += dst_memb->size;
		} else {
		    HDmemmove (buf+offset, buf+src_memb->offset,
			       src_memb->size);
		    offset += src_memb->size;
		}
	    }

	    /*
	     * For each source member which will be present in the
	     * destination, convert the member to the destination type if it
	     * is larger than the source type (that is, has not been converted
	     * yet).  Then copy the member to the destination offset in the
	     * background buffer.
	     */
	    for (i=src->u.compnd.nmembs-1; i>=0; --i) {
		if (src2dst[i]<0) continue;
		src_memb = src->u.compnd.memb + i;
		dst_memb = dst->u.compnd.memb + src2dst[i];

		if (dst_memb->size > src_memb->size) {
		    offset -= src_memb->size;
		    if (H5T_convert(priv->memb_path[i],
				    priv->src_memb_id[i],
				    priv->dst_memb_id[src2dst[i]],
				    priv->memb_nelmts[i],
				    0, /*no striding*/
				    buf+offset, bkg+dst_memb->offset,dset_xfer_plist)<0) {
			HRETURN_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL,
				      "unable to convert compound data type "
				      "member");
		    }
		} else {
		    offset -= dst_memb->size;
		}
		HDmemmove (bkg+dst_memb->offset, buf+offset, dst_memb->size);
	    }
	    assert (0==offset);

	    /*
	     * Update buf and background.
	     */
	    buf += src_delta;
	    bkg += dst_delta;
	}

	/*
	 * Copy the background buffer back into the in-place conversion
	 * buffer.
	 */
	HDmemcpy (_buf, _bkg, nelmts*dst->size);
	break;

    default:
	/* Some other command we don't know about yet.*/
	HRETURN_ERROR (H5E_DATATYPE, H5E_UNSUPPORTED, FAIL,
		       "unknown conversion command");
    }
    
    FUNC_LEAVE (SUCCEED);
}


/*-------------------------------------------------------------------------
 * Function:	H5T_conv_struct_opt
 *
 * Purpose:	Converts between compound data types in a manner more
 *		efficient than the general-purpose H5T_conv_struct()
 *		function.  This function isn't applicable if the destination
 *		is larger than the source type. This is a soft conversion
 *		function.  The algorithm is basically:
 *
 * 		For each member of the struct
 *		  If sizeof detination type <= sizeof source type then
 *		    Convert member to destination type for all elements
 *		    Move memb to BKG buffer for all elements
 *		  Else
 *		    Move member as far left as possible for all elements
 *		  
 *		For each member of the struct (in reverse order)
 *		  If not destination type then
 *		    Convert member to destination type for all elements
 *		    Move member to correct position in BKG for all elements
 *
 *		Copy BKG to BUF for all elements
 *
 * Return:	Non-negative on success/Negative on failure
 *
 * Programmer:	Robb Matzke
 *		Thursday, January 22, 1998
 *
 * Modifications:
 *		Robb Matzke, 1999-06-16
 *		Added support for non-zero strides. If STRIDE is non-zero
 *		then convert one value at each memory location advancing
 *		STRIDE bytes each time; otherwise assume both source and
 *		destination values are packed.
 *
 * 		Robb Matzke, 1999-06-16
 *		If the source and destination data structs are the same size
 *		then we can convert on a field-by-field basis instead of an
 *		element by element basis. In other words, for all struct
 *		elements being converted by this function call, first convert
 *		all of the field1's, then all field2's, etc. This can
 *		drastically reduce the number of calls to H5T_convert() and
 *		thereby eliminate most of the conversion constant overhead.
 *-------------------------------------------------------------------------
 */
herr_t
H5T_conv_struct_opt(hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata,
		    size_t nelmts, size_t stride, void *_buf, void *_bkg, hid_t dset_xfer_plist)
{
    uint8_t	*buf = (uint8_t *)_buf;	/*cast for pointer arithmetic	*/
    uint8_t	*bkg = (uint8_t *)_bkg;	/*background pointer arithmetic	*/
    uint8_t	*xbuf = NULL;		/*temporary pointer into `buf'	*/
    uint8_t	*xbkg = NULL;		/*temporary pointer into `bkg'	*/
    H5T_t	*src = NULL;		/*source data type		*/
    H5T_t	*dst = NULL;		/*destination data type		*/
    intn	*src2dst = NULL;	/*maps src member to dst member	*/
    H5T_cmemb_t	*src_memb = NULL;	/*source struct member descript.*/
    H5T_cmemb_t	*dst_memb = NULL;	/*destination struct memb desc.	*/
    size_t	src_memb_size;		/*sizeof single source member	*/
    size_t	dst_memb_size;		/*sizeof single destination memb*/
    size_t	offset;			/*byte offset wrt struct	*/
    uintn	elmtno;			/*element counter		*/
    intn	i, j;			/*counters			*/
    H5T_conv_struct_t *priv = NULL;	/*private data			*/

    FUNC_ENTER (H5T_conv_struct_opt, FAIL);

    switch (cdata->command) {
    case H5T_CONV_INIT:
	/*
	 * First, determine if this conversion function applies to the
	 * conversion path SRC_ID-->DST_ID.  If not, return failure;
	 * otherwise initialize the `priv' field of `cdata' with information
	 * that remains (almost) constant for this conversion path.
	 */
	if (H5I_DATATYPE != H5I_get_type(src_id) ||
	    NULL == (src = H5I_object(src_id)) ||
	    H5I_DATATYPE != H5I_get_type(dst_id) ||
	    NULL == (dst = H5I_object(dst_id))) {
	    HRETURN_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a data type");
	}
	assert (H5T_COMPOUND==src->type);
	assert (H5T_COMPOUND==dst->type);

	/* Initialize data which is relatively constant */
	if (H5T_conv_struct_init (src, dst, cdata)<0) {
	    HRETURN_ERROR (H5E_DATATYPE, H5E_CANTINIT, FAIL,
			   "unable to initialize conversion data");
	}
	priv = (H5T_conv_struct_t *)(cdata->priv);
	src2dst = priv->src2dst;
	
	/*
	 * If the destination type is not larger than the source type then
	 * this conversion function is guaranteed to work (provided all
	 * members can be converted also). Otherwise the determination is
	 * quite a bit more complicated. Essentially we have to make sure
	 * that there is always room in the source buffer to do the
	 * conversion of a member in place. This is basically the same pair
	 * of loops as in the actual conversion except it checks that there
	 * is room for each conversion instead of actually doing anything.
	 */
	if (dst->size > src->size) {
	    for (i=0, offset=0; i<src->u.compnd.nmembs; i++) {
		if (src2dst[i]<0) continue;
		src_memb = src->u.compnd.memb + i;
		dst_memb = dst->u.compnd.memb + src2dst[i];
		src_memb_size = src_memb->size / priv->memb_nelmts[i];
		dst_memb_size = dst_memb->size / priv->memb_nelmts[i];
		for (j=0; j<(intn)(priv->memb_nelmts[i]); j++) {
		    if (dst_memb_size > src_memb_size) {
			offset += src_memb_size;
		    }
		}
	    }
	    for (i=src->u.compnd.nmembs-1; i>=0; --i) {
		if (src2dst[i]<0) continue;
		src_memb = src->u.compnd.memb + i;
		dst_memb = dst->u.compnd.memb + src2dst[i];
		src_memb_size = src_memb->size / priv->memb_nelmts[i];
		dst_memb_size = dst_memb->size / priv->memb_nelmts[i];

		for (j=priv->memb_nelmts[i]-1; j>=0; --j) {
		    if (dst_memb_size > src_memb_size) {
			offset -= src_memb_size;
			if (dst_memb_size > src->size-offset) {
			    HRETURN_ERROR(H5E_DATATYPE, H5E_UNSUPPORTED, FAIL,
					  "convertion is unsupported by this "
					  "function");
			}
		    }
		}
	    }
	}
	break;

    case H5T_CONV_FREE:
	/*
	 * Free the private conversion data.
	 */
	priv = (H5T_conv_struct_t *)(cdata->priv);
	H5MM_xfree(priv->src2dst);
	H5MM_xfree(priv->src_memb_id);
	H5MM_xfree(priv->dst_memb_id);
	H5MM_xfree(priv->memb_path);
	H5MM_xfree(priv->memb_nelmts);
	cdata->priv = priv = H5MM_xfree (priv);
	break;

    case H5T_CONV_CONV:
	/*
	 * Conversion.
	 */
	if (H5I_DATATYPE != H5I_get_type(src_id) ||
	    NULL == (src = H5I_object(src_id)) ||
	    H5I_DATATYPE != H5I_get_type(dst_id) ||
	    NULL == (dst = H5I_object(dst_id))) {
	    HRETURN_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a data type");
	}

	/* Update cached data if necessary */
	if (cdata->recalc &&
	    H5T_conv_struct_init (src, dst, cdata)<0) {
	    HRETURN_ERROR (H5E_DATATYPE, H5E_CANTINIT, FAIL,
			   "unable to initialize conversion data");
	}
	priv = (H5T_conv_struct_t *)(cdata->priv);
	src2dst = priv->src2dst;
	assert(priv);
	assert(bkg && cdata->need_bkg>=H5T_BKG_TEMP);

	/*
	 * Insure that members are sorted.
	 */
	H5T_sort_value(src, NULL);
	H5T_sort_value(dst, NULL);

	/*
	 * For each member where the destination is not larger than the
	 * source, stride through all the elements converting only that member
	 * in each element and then copying the element to its final
	 * destination in the bkg buffer. Otherwise move the element as far
	 * left as possible in the buffer.
	 */
	for (i=0, offset=0; i<src->u.compnd.nmembs; i++) {
	    if (src2dst[i]<0) continue;
	    src_memb = src->u.compnd.memb + i;
	    dst_memb = dst->u.compnd.memb + src2dst[i];
	    src_memb_size = src_memb->size / priv->memb_nelmts[i];
	    dst_memb_size = dst_memb->size / priv->memb_nelmts[i];

	    for (j=0; j<(intn)(priv->memb_nelmts[i]); j++) {
		if (dst_memb_size <= src_memb_size) {
		    xbuf = buf + src_memb->offset + j*src_memb_size;
		    xbkg = bkg + dst_memb->offset + j*dst_memb_size;
		    if (H5T_convert(priv->memb_path[i],
				    priv->src_memb_id[i],
				    priv->dst_memb_id[src2dst[i]],
				    nelmts,
				    stride?stride:src->size,
				    xbuf, xbkg,dset_xfer_plist)<0) {
			HRETURN_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL,
				      "unable to convert compound data "
				      "type member");
		    }
		    for (elmtno=0; elmtno<nelmts; elmtno++) {
			HDmemmove(xbkg, xbuf, dst_memb_size);
			xbuf += stride ? stride : src->size;
			xbkg += stride ? stride : dst->size;
		    }
		} else {
		    for (xbuf=buf, elmtno=0; elmtno<nelmts; elmtno++) {
			HDmemmove(xbuf+offset,
				  xbuf+src_memb->offset+j*src_memb_size,
				  src_memb_size);
			xbuf += stride ? stride : src->size;
		    }
		    offset += src_memb_size;
		}
	    }
	}

	/*
	 * Work from right to left, converting those members that weren't
	 * converted in the previous loop (those members where the destination
	 * is larger than the source) and them to their final position in the
	 * bkg buffer.
	 */
	for (i=src->u.compnd.nmembs-1; i>=0; --i) {
	    if (src2dst[i]<0) continue;
	    src_memb = src->u.compnd.memb + i;
	    dst_memb = dst->u.compnd.memb + src2dst[i];
	    src_memb_size = src_memb->size / priv->memb_nelmts[i];
	    dst_memb_size = dst_memb->size / priv->memb_nelmts[i];

	    for (j=priv->memb_nelmts[i]-1; j>=0; --j) {
		if (dst_memb_size > src_memb_size) {
		    offset -= src_memb_size;
		    xbuf = buf + offset;
		    xbkg = bkg + dst_memb->offset + j*dst_memb_size;
		    if (H5T_convert(priv->memb_path[i],
				    priv->src_memb_id[i],
				    priv->dst_memb_id[src2dst[i]],
				    nelmts, stride?stride:src->size,
				    xbuf, xbkg, dset_xfer_plist)<0) {
			HRETURN_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL,
				      "unable to convert compound data "
				      "type member");
		    }
		    for (elmtno=0; elmtno<nelmts; elmtno++) {
			HDmemmove(xbkg, xbuf, dst_memb_size);
			xbuf += stride ? stride : src->size;
			xbkg += stride ? stride : dst->size;
		    }
		}
	    }
	}

	/* Move background into buffer */
	for (xbuf=buf, xbkg=bkg, elmtno=0; elmtno<nelmts; elmtno++) {
	    HDmemmove(xbuf, xbkg, dst->size);
	    xbuf += stride ? stride : dst->size;
	    xbkg += stride ? stride : dst->size;
	}
	break;

    default:
	/* Some other command we don't know about yet.*/
	HRETURN_ERROR (H5E_DATATYPE, H5E_UNSUPPORTED, FAIL,
		       "unknown conversion command");
    }
    
    FUNC_LEAVE (SUCCEED);
}


/*-------------------------------------------------------------------------
 * Function:	H5T_conv_enum_init
 *
 * Purpose:	Initialize information for H5T_conv_enum().
 *
 * Return:	Success:	Non-negative
 *
 *		Failure:	Negative
 *
 * Programmer:	Robb Matzke
 *              Monday, January  4, 1999
 *
 * Modifications:
 *
 *-------------------------------------------------------------------------
 */
static herr_t
H5T_conv_enum_init(H5T_t *src, H5T_t *dst, H5T_cdata_t *cdata)
{
    H5T_enum_struct_t	*priv=NULL;	/*private conversion data	*/
    intn		n;		/*src value cast as native int	*/
    intn		domain[2];	/*min and max source values	*/
    intn		*map=NULL;	/*map from src value to dst idx	*/
    intn		length;		/*nelmts in map array		*/
    herr_t		ret_value=FAIL;	/*return value			*/
    intn		i, j;		/*counters			*/
    
    FUNC_ENTER(H5T_conv_enum_init, FAIL);

    cdata->need_bkg = H5T_BKG_NO;
    if (NULL==(priv=cdata->priv=H5MM_calloc(sizeof(*priv)))) {
	HRETURN_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL,
		      "memory allocation failed");
    }
    if (0==src->u.enumer.nmembs) {
	HRETURN(SUCCEED);
    }

    /*
     * Check that the source symbol names are a subset of the destination
     * symbol names and build a map from source member index to destination
     * member index.
     */
    H5T_sort_name(src, NULL);
    H5T_sort_name(dst, NULL);
    if (NULL==(priv->src2dst=H5MM_malloc(src->u.enumer.nmembs*sizeof(int)))) {
	HRETURN_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL,
		      "memory allocation failed");;
    }
    for (i=0, j=0;
	 i<src->u.enumer.nmembs && j<dst->u.enumer.nmembs;
	 i++, j++) {
	while (j<dst->u.enumer.nmembs &&
	       HDstrcmp(src->u.enumer.name[i], dst->u.enumer.name[j])) j++;
	if (j>=dst->u.enumer.nmembs) {
	    HRETURN_ERROR(H5E_DATATYPE, H5E_UNSUPPORTED, FAIL,
			  "source type is not a subset of destination type");
	}
	priv->src2dst[i] = j;
    }

    /*
     * The conversion function will use an O(log N) lookup method for each
     * value converted. However, if all of the following constraints are met
     * then we can build a perfect hash table and use an O(1) lookup method.
     *
     *	  A: The source data type size matches one of our native data type
     *	     sizes.
     *	     
     *	  B: After casting the source value bit pattern to a native type
     *	     the size of the range of values is less than 20% larger than
     *	     the number of values.
     *
     * If this special case is met then we use the source bit pattern cast as
     * a native integer type as an index into the `val2dst'. The values of
     * that array are the index numbers in the destination type or negative
     * if the entry is unused.
     */
    if (1==src->size || sizeof(short)==src->size || sizeof(int)==src->size) {
	for (i=0; i<src->u.enumer.nmembs; i++) {
	    if (1==src->size) {
		n = *((signed char*)(src->u.enumer.value+i));
	    } else if (sizeof(short)==src->size) {
		n = *((short*)(src->u.enumer.value+i*src->size));
	    } else {
		n = *((int*)(src->u.enumer.value+i*src->size));
	    }
	    if (0==i) {
		domain[0] = domain[1] = n;
	    } else {
		domain[0] = MIN(domain[0], n);
		domain[1] = MAX(domain[1], n);
	    }
	}

	length = (domain[1]-domain[0])+1;
	if (src->u.enumer.nmembs<2 ||
	    (double)length/src->u.enumer.nmembs<1.2) {
	    priv->base = domain[0];
	    priv->length = length;
	    if (NULL==(map=H5MM_malloc(length*sizeof(int)))) {
		HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL,
			    "memory allocation failed");
	    }
	    for (i=0; i<length; i++) map[i] = -1; /*entry unused*/
	    for (i=0; i<src->u.enumer.nmembs; i++) {
		if (1==src->size) {
		    n = *((signed char*)(src->u.enumer.value+i));
		} else if (sizeof(short)==src->size) {
		    n = *((short*)(src->u.enumer.value+i*src->size));
		} else {
		    n = *((int*)(src->u.enumer.value+i*src->size));
		}
		n -= priv->base;
		assert(n>=0 && n<priv->length);
		assert(map[n]<0);
		map[n] = priv->src2dst[i];
	    }

	    /*
	     * Replace original src2dst array with our new one. The original
	     * was indexed by source member number while the new one is
	     * indexed by source values.
	     */
	    H5MM_xfree(priv->src2dst);
	    priv->src2dst = map;
	    HGOTO_DONE(SUCCEED);
	} else {
	    /* Sort source type by value and adjust src2dst[] appropriately */
	    H5T_sort_value(src, priv->src2dst);
	}
    }
    ret_value = SUCCEED;

 done:
    if (ret_value<0 && priv) {
	H5MM_xfree(priv->src2dst);
	H5MM_xfree(priv);
	cdata->priv = NULL;
    }
    FUNC_LEAVE(ret_value);
}


/*-------------------------------------------------------------------------
 * Function:	H5T_conv_enum
 *
 * Purpose:	Converts one type of enumerated data to another.
 *
 * Return:	Success:	Non-negative
 *
 *		Failure:	negative
 *
 * Programmer:	Robb Matzke
 *              Monday, January  4, 1999
 *
 * Modifications:
 *		Robb Matzke, 1999-06-16
 *		Added support for non-zero strides. If STRIDE is non-zero
 *		then convert one value at each memory location advancing
 *		STRIDE bytes each time; otherwise assume both source and
 *		destination values are packed.
 *-------------------------------------------------------------------------
 */
herr_t
H5T_conv_enum(hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata, size_t nelmts,
	      size_t stride, void *_buf, void UNUSED *bkg, hid_t UNUSED dset_xfer_plist)
{
    uint8_t	*buf = (uint8_t*)_buf;	/*cast for pointer arithmetic	*/
    H5T_t	*src=NULL, *dst=NULL;	/*src and dst data types	*/
    uint8_t	*s=NULL, *d=NULL;	/*src and dst BUF pointers	*/
    intn	src_delta, dst_delta;	/*conversion strides		*/
    intn	n;			/*src value cast as native int	*/
    size_t	i;			/*counters			*/
    H5T_enum_struct_t *priv = (H5T_enum_struct_t*)(cdata->priv);
    
    FUNC_ENTER(H5T_conv_enum, FAIL);
    switch (cdata->command) {
    case H5T_CONV_INIT:
	/*
	 * Determine if this conversion function applies to the conversion
	 * path SRC_ID->DST_ID.  If not return failure; otherwise initialize
	 * the `priv' field of `cdata' with information about the underlying
	 * integer conversion.
	 */
	if (H5I_DATATYPE != H5I_get_type(src_id) ||
	    NULL == (src = H5I_object(src_id)) ||
	    H5I_DATATYPE != H5I_get_type(dst_id) ||
	    NULL == (dst = H5I_object(dst_id))) {
	    HRETURN_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a data type");
	}
	assert (H5T_ENUM==src->type);
	assert (H5T_ENUM==dst->type);
	if (H5T_conv_enum_init(src, dst, cdata)<0) {
	    HRETURN_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL,
			  "unable to initialize private data");
	}
	break;

    case H5T_CONV_FREE:
#ifdef H5T_DEBUG
	if (H5DEBUG(T)) {
	    fprintf(H5DEBUG(T), "      Using %s mapping function%s\n",
		    priv->length?"O(1)":"O(log N)",
		    priv->length?"":", where N is the number of enum members");
	}
#endif
	if (priv) {
	    H5MM_xfree(priv->src2dst);
	    H5MM_xfree(priv);
	}
	cdata->priv = NULL;
	break;

    case H5T_CONV_CONV:
	if (H5I_DATATYPE != H5I_get_type(src_id) ||
	    NULL == (src = H5I_object(src_id)) ||
	    H5I_DATATYPE != H5I_get_type(dst_id) ||
	    NULL == (dst = H5I_object(dst_id))) {
	    HRETURN_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a data type");
	}
	assert (H5T_ENUM==src->type);
	assert (H5T_ENUM==dst->type);

	if (priv->length) {
	    /* Use O(1) lookup */
	    H5T_sort_name(src, NULL);
	    H5T_sort_name(dst, NULL);
	} else {
	    /* Use O(log N) lookup */
	    H5T_sort_value(src, NULL); /*yes, by value*/
	    H5T_sort_name(dst, NULL); /*yes, by name*/
	}
	
	/*
	 * Direction of conversion.
	 */
	if (stride) {
	    src_delta = dst_delta = stride;
	    s = d = buf;
	} else if (dst->size <= src->size) {
	    src_delta = (int)src->size; /*overflow shouldn't be possible*/
	    dst_delta = (int)dst->size; /*overflow shouldn't be possible*/
	    s = d = buf;
	} else {
	    src_delta = -(int)src->size; /*overflow shouldn't be possible*/
	    dst_delta = -(int)dst->size; /*overflow shouldn't be possible*/
	    s = buf + (nelmts-1) * src->size;
	    d = buf + (nelmts-1) * dst->size;
	}

	for (i=0; i<nelmts; i++, s+=src_delta, d+=dst_delta) {
	    if (priv->length) {
		/* Use O(1) lookup */
		if (1==src->size) {
		    n = *((signed char*)s);
		} else if (sizeof(short)==src->size) {
		    n = *((short*)s);
		} else {
		    n = *((int*)s);
		}
		n -= priv->base;
		if (n<0 || n>=priv->length || priv->src2dst[n]<0) {
		    if (!H5T_overflow_g ||
			(H5T_overflow_g)(src_id, dst_id, s, d)<0) {
			HDmemset(d, 0xff, dst->size);
		    }
		} else {
		    HDmemcpy(d,
			     dst->u.enumer.value+priv->src2dst[n]*dst->size,
			     dst->size);
		}
	    } else {
		/* Use O(log N) lookup */
		int lt = 0;
		int rt = src->u.enumer.nmembs;
		int md, cmp;
		while (lt<rt) {
		    md = (lt+rt)/2;
		    cmp = HDmemcmp(s, src->u.enumer.value+md*src->size,
				   src->size);
		    if (cmp<0) {
			rt = md;
		    } else if (cmp>0) {
			lt = md+1;
		    } else {
			break;
		    }
		}
		if (lt>=rt) {
		    if (!H5T_overflow_g ||
			(H5T_overflow_g)(src_id, dst_id, s, d)<0) {
			HDmemset(d, 0xff, dst->size);
		    }
		} else {
		    HDmemcpy(d,
			     dst->u.enumer.value+priv->src2dst[md]*dst->size,
			     dst->size);
		}
	    }
	}
	break;

    default:
	/* Some other command we don't know about yet.*/
	HRETURN_ERROR (H5E_DATATYPE, H5E_UNSUPPORTED, FAIL,
		       "unknown conversion command");
    }
    FUNC_LEAVE(SUCCEED);
}


/*-------------------------------------------------------------------------
 * Function:	H5T_conv_vlen
 *
 * Purpose:	Converts between VL data types in memory and on disk.
 *		This is a soft conversion function.  The algorithm is
 *		basically:
 *
 *      	For every VL struct in the main buffer:
 *		  1. Allocate space for temporary dst VL data (reuse buffer
 *		     if possible) 
 *                2. Copy VL data from src buffer into dst buffer
 *                3. Convert VL data into dst representation
 *                4. Allocate buffer in dst heap
 *                5. Write dst VL data into dst heap
 *                6. Store (heap ID or pointer) and length in main dst buffer
 *
 * Return:	Non-negative on success/Negative on failure
 *
 * Programmer:	Quincey Koziol
 *		Wednesday, May 26, 1999
 *
 * Modifications:
 *
 *		Quincey Koziol, 2 July, 1999
 *		Enabled support for non-zero strides. If STRIDE is non-zero
 *		then convert one value at each memory location advancing
 *		STRIDE bytes each time; otherwise assume both source and
 *		destination values are packed.
 *
 *-------------------------------------------------------------------------
 */
herr_t
H5T_conv_vlen(hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata, size_t nelmts,
	      size_t stride, void *_buf, void UNUSED *_bkg, hid_t dset_xfer_plist)
{
    const H5F_xfer_t	   *xfer_parms = NULL;
    H5T_path_t	*tpath;			/* Type conversion path		     */
    hid_t   	tsrc_id = -1, tdst_id = -1;/*temporary type atoms	     */
    H5T_t	*src = NULL;		/*source data type		     */
    H5T_t	*dst = NULL;		/*destination data type		     */
    size_t	olap;			/*num overlapping elements	     */
    uint8_t	*s, *sp, *d, *dp;	/*source and dest traversal ptrs     */
    uint8_t 	**dptr;		     /*pointer to correct destination pointer*/
    size_t	src_delta, dst_delta;	/*source & destination stride	     */
    hsize_t 	seq_len;     /*the number of elements in the current sequence*/
    size_t	src_base_size, dst_base_size;/*source & destination base size*/
    size_t	src_size, dst_size;/*source & destination total size in bytes*/
    hid_t 	conv_buf_id;		/*ID for comversion buffer	     */
    void	*conv_buf_ptr;     	/*temporary conversion buffer 	     */
    hsize_t	conv_buf_size;  	/*size of conversion buffer in bytes */
    uint8_t	dbuf[64],*dbuf_ptr=dbuf;/*temp destination buffer	     */
    intn	direction;		/*direction of traversal	     */
    uintn	elmtno;			/*element number counter	     */

    FUNC_ENTER (H5T_conv_vlen, FAIL);

    switch (cdata->command) {
        case H5T_CONV_INIT:
            /*
             * First, determine if this conversion function applies to the
             * conversion path SRC_ID-->DST_ID.  If not, return failure;
             * otherwise initialize the `priv' field of `cdata' with information
             * that remains (almost) constant for this conversion path.
             */
            if (H5I_DATATYPE != H5I_get_type(src_id) || NULL == (src = H5I_object(src_id)) ||
                H5I_DATATYPE != H5I_get_type(dst_id) || NULL == (dst = H5I_object(dst_id))) {
                    HRETURN_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a data type");
            }
            assert (H5T_VLEN==src->type);
            assert (H5T_VLEN==dst->type);

#ifdef LATER
/* QAK - Set up conversion function? */
            if (H5T_conv_vlen_init (src, dst, cdata)<0) {
                HRETURN_ERROR (H5E_DATATYPE, H5E_CANTINIT, FAIL,
                       "unable to initialize conversion data");
            }
#endif /* LATER */
            break;

        case H5T_CONV_FREE:
/* QAK - Nothing to do currently */
            break;

        case H5T_CONV_CONV:
            /*
             * Conversion.
             */
            if (H5I_DATATYPE != H5I_get_type(src_id) || NULL == (src = H5I_object(src_id)) ||
                H5I_DATATYPE != H5I_get_type(dst_id) || NULL == (dst = H5I_object(dst_id))) {
                    HRETURN_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a data type");
            }

            /* Get the dataset transfer property list */
            if (H5P_DEFAULT == dset_xfer_plist) {
                xfer_parms = &H5F_xfer_dflt;
            } else if (H5P_DATA_XFER != H5P_get_class(dset_xfer_plist) ||
                   NULL == (xfer_parms = H5I_object(dset_xfer_plist))) {
                HRETURN_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not xfer parms");
            }

            /*
             * 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->size==dst->size || stride>0) {
                olap = nelmts;
                sp = dp = (uint8_t*)_buf;
                direction = 1;
            } else if (src->size>=dst->size) {
                olap = ((dst->size)/(src->size-dst->size))+1; /* potentially this uses the destination buffer 1 extra time, but its faster that floating-point calcs */
                sp = dp = (uint8_t*)_buf;
                direction = 1;
            } else {
                olap = nelmts-(((src->size)/(dst->size-src->size))+1); /* potentially this uses the destination buffer 1 extra time, but its faster that floating-point calcs */
                sp = (uint8_t*)_buf + (nelmts-1) * (stride ? stride : src->size);
                dp = (uint8_t*)_buf + (nelmts-1) * (stride ? stride : dst->size);
                direction = -1;
            }

            /*
             * Direction & size of buffer traversal.
             */
            src_delta = direction * (stride ? stride : src->size);
            dst_delta = direction * (stride ? stride : dst->size);

            /*
             * If the source and destination buffers overlap then use a
             * temporary buffer for the destination.
             */
            if (direction>0) {
                dptr = &dbuf_ptr;
            } else {
                dptr = &dp;
            }

            /* Get the size of the base types in src & dst */
            src_base_size=H5T_get_size(src->parent);
            dst_base_size=H5T_get_size(dst->parent);

            /* Get initial conversion buffer */
            conv_buf_size=MAX(src_base_size,dst_base_size);
            if((conv_buf_id=H5TB_get_buf(conv_buf_size,FALSE,&conv_buf_ptr))==FAIL)
                HRETURN_ERROR (H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed for type conversion");

            /* Set up conversion path for base elements */
            tpath = H5T_path_find(src->parent, dst->parent, NULL, NULL);
            if (NULL==(tpath=H5T_path_find(src->parent, dst->parent, NULL, NULL))) {
                HRETURN_ERROR(H5E_DATATYPE, H5E_UNSUPPORTED, FAIL, "unable to convert between src and dest data types");
            } else if (!H5T_IS_NOOP(tpath)) {
                if ((tsrc_id = H5I_register(H5I_DATATYPE, H5T_copy(src->parent, H5T_COPY_ALL)))<0 ||
                    (tdst_id = H5I_register(H5I_DATATYPE, H5T_copy(dst->parent, H5T_COPY_ALL)))<0) {
                    HRETURN_ERROR(H5E_DATASET, H5E_CANTREGISTER, FAIL, "unable to register types for conversion");
                }
            }

            for (elmtno=0; elmtno<nelmts; elmtno++) {
                s = sp;
                d = *dptr;

                /* Get length of sequences in bytes */
                seq_len=(*(src->u.vlen.getlen))(src->u.vlen.f,s);
                src_size=seq_len*src_base_size;
                dst_size=seq_len*dst_base_size;

                /* Check if conversion buffer is large enough, resize if necessary */
                if(conv_buf_size<MAX(src_size,dst_size)) {
                    conv_buf_size=MAX(src_size,dst_size);
                    if(H5TB_resize_buf(conv_buf_id,conv_buf_size,&conv_buf_ptr)<0)
                        HRETURN_ERROR (H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed for type conversion");
                } /* end if */

                /* Read in VL sequence */
                if((*(src->u.vlen.read))(src->u.vlen.f,s,conv_buf_ptr,src_size)<0)
                    HRETURN_ERROR(H5E_DATATYPE, H5E_READERROR, FAIL, "can't read VL data");

                /* Convert VL sequence */
                if (H5T_convert(tpath, tsrc_id, tdst_id, seq_len, 0, conv_buf_ptr, NULL, dset_xfer_plist)<0)
                    HRETURN_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL, "datatype conversion failed");

                /* Write sequence to destination location */
                if((*(dst->u.vlen.write))(xfer_parms,dst->u.vlen.f,d,conv_buf_ptr,seq_len,dst_base_size)<0)
                    HRETURN_ERROR(H5E_DATATYPE, H5E_WRITEERROR, FAIL, "can't write VL data");

                /*
                 * 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->size);
                sp += src_delta;
                dp += dst_delta;

                /* switch destination pointer around when the olap gets to 0 */
                if(--olap==0) {
                    if(dptr==&dbuf_ptr)
                        dptr=&dp;
                    else
                        dptr=&dbuf_ptr;
                } /* end if */
            }

            /* Release the conversion buffer */
            H5TB_release_buf(conv_buf_id);

            /* Release the temporary datatype IDs used */
            if (tsrc_id >= 0) H5I_dec_ref(tsrc_id);
            if (tdst_id >= 0) H5I_dec_ref(tdst_id);

            break;

        default:    /* Some other command we don't know about yet.*/
            HRETURN_ERROR (H5E_DATATYPE, H5E_UNSUPPORTED, FAIL,
                   "unknown conversion command");
    }   /* end switch */
    
    FUNC_LEAVE (SUCCEED);
}


/*-------------------------------------------------------------------------
 * Function:	H5T_conv_i_i
 *
 * Purpose:	Convert one integer type to another.  This is the catch-all
 *		function for integer conversions and is probably not
 *		particularly fast.
 *
 * Return:	Non-negative on success/Negative on failure
 *
 * Programmer:	Robb Matzke
 *		Wednesday, June 10, 1998
 *
 * Modifications:
 *		Robb Matzke, 7 Jul 1998
 *		Added overflow handling.
 *
 *		Robb Matzke, 1999-06-16
 *		Added support for non-zero strides. If STRIDE is non-zero
 *		then convert one value at each memory location advancing
 *		STRIDE bytes each time; otherwise assume both source and
 *		destination values are packed.
 *-------------------------------------------------------------------------
 */
herr_t
H5T_conv_i_i (hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata, size_t nelmts,
	      size_t stride, void *buf, void UNUSED *bkg, hid_t UNUSED dset_xfer_plist)
{
    H5T_t	*src = NULL;		/*source data type		*/
    H5T_t	*dst = NULL;		/*destination data type		*/
    intn	direction;		/*direction of traversal	*/
    size_t	elmtno;			/*element number		*/
    size_t	half_size;		/*half the type size		*/
    size_t	olap;			/*num overlapping elements	*/
    uint8_t	*s, *sp, *d, *dp;	/*source and dest traversal ptrs*/
    uint8_t	dbuf[64];		/*temp destination buffer	*/
    size_t	first;
    ssize_t	sfirst;			/*a signed version of `first'	*/
    size_t	i;
    
    FUNC_ENTER (H5T_conv_i_i, FAIL);

    switch (cdata->command) {
    case H5T_CONV_INIT:
	if (H5I_DATATYPE!=H5I_get_type (src_id) ||
	    NULL==(src=H5I_object (src_id)) ||
	    H5I_DATATYPE!=H5I_get_type (dst_id) ||
	    NULL==(dst=H5I_object (dst_id))) {
	    HRETURN_ERROR (H5E_ARGS, H5E_BADTYPE, FAIL, "not a data type");
	}
	if (H5T_ORDER_LE!=src->u.atomic.order &&
	    H5T_ORDER_BE!=src->u.atomic.order) {
	    HRETURN_ERROR (H5E_DATATYPE, H5E_UNSUPPORTED, FAIL,
			   "unsupported byte order");
	}
	if (H5T_ORDER_LE!=dst->u.atomic.order &&
	    H5T_ORDER_BE!=dst->u.atomic.order) {
	    HRETURN_ERROR (H5E_DATATYPE, H5E_UNSUPPORTED, FAIL,
			   "unsupported byte order");
	}
	if (dst->size>sizeof dbuf) {
	    HRETURN_ERROR (H5E_DATATYPE, H5E_UNSUPPORTED, FAIL,
			   "destination size is too large");
	}
	cdata->need_bkg = H5T_BKG_NO;
	break;
	
    case H5T_CONV_FREE:
	break;

    case H5T_CONV_CONV:
	/* Get the data types */
	if (H5I_DATATYPE!=H5I_get_type (src_id) ||
	    NULL==(src=H5I_object (src_id)) ||
	    H5I_DATATYPE!=H5I_get_type (dst_id) ||
	    NULL==(dst=H5I_object (dst_id))) {
	    HRETURN_ERROR (H5E_ARGS, H5E_BADTYPE, FAIL, "not a data type");
	}

	/*
	 * 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->size==dst->size || stride) {
	    sp = dp = (uint8_t*)buf;
	    direction = 1;
	    olap = nelmts;
	} else if (src->size>=dst->size) {
	    double olap_d = HDceil((double)(dst->size)/
				   (double)(src->size-dst->size));
	    
	    olap = (size_t)olap_d;
	    sp = dp = (uint8_t*)buf;
	    direction = 1;
	} else {
	    double olap_d = HDceil((double)(src->size)/
				   (double)(dst->size-src->size));
	    olap = (size_t)olap_d;
	    sp = (uint8_t*)buf + (nelmts-1) * src->size;
	    dp = (uint8_t*)buf + (nelmts-1) * dst->size;
	    direction = -1;
	}

	/* The conversion loop */
	for (elmtno=0; elmtno<nelmts; elmtno++) {

	    /*
	     * If the source and destination buffers overlap then use a
	     * temporary buffer for the destination.
	     */
	    if (direction>0) {
		s = sp;
		d = elmtno<olap ? dbuf : dp;
	    } else {
		s = sp;
		d = elmtno+olap >= nelmts ? dbuf : dp;
	    }
#ifndef NDEBUG
	    /* I don't quite trust the overlap calculations yet --rpm */
	    if (d==dbuf) {
		assert ((dp>=sp && dp<sp+src->size) ||
			(sp>=dp && sp<dp+dst->size));
	    } else {
		assert ((dp<sp && dp+dst->size<=sp) ||
			(sp<dp && sp+src->size<=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->u.atomic.order) {
		half_size = src->size/2;
		for (i=0; i<half_size; i++) {
		    uint8_t tmp = s[src->size-(i+1)];
		    s[src->size-(i+1)] = s[i];
		    s[i] = tmp;
		}
	    }

	    /*
	     * What is the bit number for the msb bit of S which is set? The
	     * bit number is relative to the significant part of the number.
	     */
	    sfirst = H5T_bit_find (s, src->u.atomic.offset, src->u.atomic.prec,
				   H5T_BIT_MSB, TRUE);
	    first = (size_t)sfirst;

	    if (sfirst<0) {
		/*
		 * The source has no bits set and must therefore be zero.
		 * Set the destination to zero.
		 */
		H5T_bit_set (d, dst->u.atomic.offset, dst->u.atomic.prec,
			     FALSE);
		
	    } else if (H5T_SGN_NONE==src->u.atomic.u.i.sign &&
		       H5T_SGN_NONE==dst->u.atomic.u.i.sign) {
		/*
		 * Source and destination are both unsigned, but if the
		 * source has more precision bits than the destination then
		 * it's possible to overflow.  When overflow occurs the
		 * destination will be set to the maximum possible value.
		 */
		if (src->u.atomic.prec <= dst->u.atomic.prec) {
		    H5T_bit_copy (d, dst->u.atomic.offset,
				  s, src->u.atomic.offset,
				  src->u.atomic.prec);
		    H5T_bit_set (d, dst->u.atomic.offset+src->u.atomic.prec,
				 dst->u.atomic.prec-src->u.atomic.prec, FALSE);
		} else if (first>=dst->u.atomic.prec) {
		    /*overflow*/
		    if (!H5T_overflow_g ||
			(H5T_overflow_g)(src_id, dst_id, s, d)<0) {
			H5T_bit_set (d, dst->u.atomic.offset,
				     dst->u.atomic.prec, TRUE);
		    }
		} else {
		    H5T_bit_copy (d, dst->u.atomic.offset,
				  s, src->u.atomic.offset,
				  dst->u.atomic.prec);
		}
		
	    } else if (H5T_SGN_2==src->u.atomic.u.i.sign &&
		       H5T_SGN_NONE==dst->u.atomic.u.i.sign) {
		/*
		 * If the source is signed and the destination isn't then we
		 * can have overflow if the source contains more bits than
		 * the destination (destination is set to the maximum
		 * possible value) or overflow if the source is negative
		 * (destination is set to zero).
		 */
		if (first+1 == src->u.atomic.prec) {
		    /*overflow*/
		    if (!H5T_overflow_g ||
			(H5T_overflow_g)(src_id, dst_id, s, d)<0) {
			H5T_bit_set (d, dst->u.atomic.offset,
				     dst->u.atomic.prec, FALSE);
		    }
		} else if (src->u.atomic.prec < dst->u.atomic.prec) {
		    H5T_bit_copy (d, dst->u.atomic.offset,
				  s, src->u.atomic.offset,
				  src->u.atomic.prec-1);
		    H5T_bit_set (d, dst->u.atomic.offset+src->u.atomic.prec-1,
				 (dst->u.atomic.prec-src->u.atomic.prec)+1,
				 FALSE);
		} else if (first>=dst->u.atomic.prec) {
		    /*overflow*/
		    if (!H5T_overflow_g ||
			(H5T_overflow_g)(src_id, dst_id, s, d)<0) {
			H5T_bit_set (d, dst->u.atomic.offset,
				     dst->u.atomic.prec, TRUE);
		    }
		} else {
		    H5T_bit_copy (d, dst->u.atomic.offset,
				  s, src->u.atomic.offset,
				  dst->u.atomic.prec);
		}
		
	    } else if (H5T_SGN_NONE==src->u.atomic.u.i.sign &&
		       H5T_SGN_2==dst->u.atomic.u.i.sign) {
		/*
		 * If the source is not signed but the destination is then
		 * overflow can occur in which case the destination is set to
		 * the largest possible value (all bits set except the msb).
		 */
		if (first+1 >= dst->u.atomic.prec) {
		    /*overflow*/
		    if (!H5T_overflow_g ||
			(H5T_overflow_g)(src_id, dst_id, s, d)<0) {
			H5T_bit_set (d, dst->u.atomic.offset,
				     dst->u.atomic.prec-1, TRUE);
			H5T_bit_set (d, (dst->u.atomic.offset +
					 dst->u.atomic.prec-1), 1, FALSE);
		    }
		} else if (src->u.atomic.prec<dst->u.atomic.prec) {
		    H5T_bit_copy (d, dst->u.atomic.offset,
				  s, src->u.atomic.offset,
				  src->u.atomic.prec);
		    H5T_bit_set (d, dst->u.atomic.offset+src->u.atomic.prec,
				 dst->u.atomic.prec-src->u.atomic.prec, FALSE);
		} else {
		    H5T_bit_copy (d, dst->u.atomic.offset,
				  s, src->u.atomic.offset,
				  dst->u.atomic.prec);
		}
		
	    } else if (first+1 == src->u.atomic.prec) {
		/*
		 * Both the source and the destination are signed and the
		 * source value is negative.  We could experience overflow
		 * if the destination isn't wide enough in which case the
		 * destination is set to a negative number with the largest
		 * possible magnitude.
		 */
		ssize_t sfz = H5T_bit_find (s, src->u.atomic.offset,
					    src->u.atomic.prec-1, H5T_BIT_MSB,
					    FALSE);
		size_t fz = (size_t)sfz;
		
		if (sfz>=0 && fz+1>=dst->u.atomic.prec) {
		    /*overflow*/
		    if (!H5T_overflow_g ||
			(H5T_overflow_g)(src_id, dst_id, s, d)<0) {
			H5T_bit_set (d, dst->u.atomic.offset,
				     dst->u.atomic.prec-1, FALSE);
			H5T_bit_set (d, (dst->u.atomic.offset +
					 dst->u.atomic.prec-1), 1, TRUE);
		    }
		} else if (src->u.atomic.prec<dst->u.atomic.prec) {
		    H5T_bit_copy (d, dst->u.atomic.offset,
				  s, src->u.atomic.offset,
				  src->u.atomic.prec);
		    H5T_bit_set (d, dst->u.atomic.offset+src->u.atomic.prec,
				 dst->u.atomic.prec-src->u.atomic.prec, TRUE);
		} else {
		    H5T_bit_copy (d, dst->u.atomic.offset,
				  s, src->u.atomic.offset,
				  dst->u.atomic.prec);
		}
		
	    } else {
		/*
		 * Source and destination are both signed but the source
		 * value is positive.  We could have an overflow in which
		 * case the destination is set to the largest possible
		 * positive value.
		 */
		if (first+1>=dst->u.atomic.prec) {
		    /*overflow*/
		    if (!H5T_overflow_g ||
			(H5T_overflow_g)(src_id, dst_id, s, d)<0) {
			H5T_bit_set (d, dst->u.atomic.offset,
				     dst->u.atomic.prec-1, TRUE);
			H5T_bit_set (d, (dst->u.atomic.offset +
					 dst->u.atomic.prec-1), 1, FALSE);
		    }
		} else if (src->u.atomic.prec<dst->u.atomic.prec) {
		    H5T_bit_copy (d, dst->u.atomic.offset,
				  s, src->u.atomic.offset,
				  src->u.atomic.prec);
		    H5T_bit_set (d, dst->u.atomic.offset+src->u.atomic.prec,
				 dst->u.atomic.prec-src->u.atomic.prec, FALSE);
		} else {
		    H5T_bit_copy (d, dst->u.atomic.offset,
				  s, src->u.atomic.offset,
				  dst->u.atomic.prec);
		}
	    }

	    /*
	     * Set padding areas in destination.
	     */
	    if (dst->u.atomic.offset>0) {
		assert (H5T_PAD_ZERO==dst->u.atomic.lsb_pad ||
			H5T_PAD_ONE==dst->u.atomic.lsb_pad);
		H5T_bit_set (d, 0, dst->u.atomic.offset,
			     H5T_PAD_ONE==dst->u.atomic.lsb_pad);
	    }
	    if (dst->u.atomic.offset+dst->u.atomic.prec!=8*dst->size) {
		assert (H5T_PAD_ZERO==dst->u.atomic.msb_pad ||
			H5T_PAD_ONE==dst->u.atomic.msb_pad);
		H5T_bit_set (d, dst->u.atomic.offset+dst->u.atomic.prec,
			     8*dst->size - (dst->u.atomic.offset+
					    dst->u.atomic.prec),
			     H5T_PAD_ONE==dst->u.atomic.msb_pad);
	    }

	    /*
	     * Put the destination in the correct byte order.  See note at
	     * beginning of loop.
	     */
	    if (H5T_ORDER_BE==dst->u.atomic.order) {
		half_size = dst->size/2;
		for (i=0; i<half_size; i++) {
		    uint8_t tmp = d[dst->size-(i+1)];
		    d[dst->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->size);
	    if (stride) {
		sp += direction * stride;
		dp += direction * stride;
	    } else {
		sp += direction * src->size;
		dp += direction * dst->size;
	    }
	}
	
	break;

    default:
	HRETURN_ERROR (H5E_DATATYPE, H5E_UNSUPPORTED, FAIL,
		       "unknown conversion command");
    }

    FUNC_LEAVE (SUCCEED);
}


/*-------------------------------------------------------------------------
 * 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:	Non-negative on success/Negative on failure
 *
 * Programmer:	Robb Matzke
 *		Tuesday, June 23, 1998
 *
 * Modifications:
 *		Robb Matzke, 7 Jul 1998
 *		Added overflow handling.
 *
 *		Robb Matzke, 1999-06-16
 *		Added support for non-zero strides. If STRIDE is non-zero
 *		then convert one value at each memory location advancing
 *		STRIDE bytes each time; otherwise assume both source and
 *		destination values are packed.
 *-------------------------------------------------------------------------
 */
herr_t
H5T_conv_f_f (hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata, size_t nelmts,
	      size_t stride, void *buf, void UNUSED *bkg, hid_t UNUSED dset_xfer_plist)
{
    /* 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_t	*s, *sp, *d, *dp;	/*source and dest traversal ptrs*/
    uint8_t	dbuf[64];		/*temp destination buffer	*/

    /* Conversion-related variables */
    hssize_t	expo;			/*exponent			*/
    hssize_t	expo_max;		/*maximum possible dst exponent	*/
    size_t	msize=0;		/*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 (H5I_DATATYPE!=H5I_get_type (src_id) ||
	    NULL==(src_p=H5I_object (src_id)) ||
	    H5I_DATATYPE!=H5I_get_type (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)-1<src.u.f.esize ||
	    8*sizeof(expo)-1<dst.u.f.esize) {
	    HRETURN_ERROR (H5E_DATATYPE, H5E_UNSUPPORTED, FAIL,
			   "exponent field is too large");
	}
	cdata->need_bkg = H5T_BKG_NO;
	break;

    case H5T_CONV_FREE:
	break;

    case H5T_CONV_CONV:
	/* Get the data types */
	if (H5I_DATATYPE!=H5I_get_type (src_id) ||
	    NULL==(src_p=H5I_object (src_id)) ||
	    H5I_DATATYPE!=H5I_get_type (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 || stride) {
	    sp = dp = (uint8_t*)buf;
	    direction = 1;
	    olap = nelmts;
	} else if (src_p->size>=dst_p->size) {
	    double olap_d = HDceil((double)(dst_p->size)/
				   (double)(src_p->size-dst_p->size));
	    olap = (size_t)olap_d;
	    sp = dp = (uint8_t*)buf;
	    direction = 1;
	} else {
	    double olap_d = HDceil((double)(src_p->size)/
				   (double)(dst_p->size-src_p->size));
	    olap = (size_t)olap_d;
	    sp = (uint8_t*)buf + (nelmts-1) * src_p->size;
	    dp = (uint8_t*)buf + (nelmts-1) * dst_p->size;
	    direction = -1;
	}

	/* The conversion loop */
	for (elmtno=0; elmtno<nelmts; elmtno++) {
	    /*
	     * If the source and destination buffers overlap then use a
	     * temporary buffer for the destination.
	     */
	    if (direction>0) {
		s = sp;
		d = elmtno<olap ? dbuf : dp;
	    } else {
		s = sp;
		d = elmtno+olap >= nelmts ? dbuf : dp;
	    }
#ifndef NDEBUG
	    /* I don't quite trust the overlap calculations yet --rpm */
	    if (d==dbuf) {
		assert ((dp>=sp && dp<sp+src_p->size) ||
			(sp>=dp && sp<dp+dst_p->size));
	    } else {
		assert ((dp<sp && dp+dst_p->size<=sp) ||
			(sp<dp && sp+src_p->size<=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; i<half_size; i++) {
		    uint8_t tmp = s[src_p->size-(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);
		HDabort();
	    }
	    
	    /*
	     * 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);
		HDabort();
	    }

	    /*
	     * 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 unless the application
		 * specifies something else.  Before calling the overflow
		 * handler make sure the source buffer we hand it is in the
		 * original byte order.
		 */
		if (H5T_overflow_g) {
		    uint8_t over_src[256];
		    assert(src_p->size<=sizeof over_src);
		    if (H5T_ORDER_BE==src.order) {
			for (i=0; i<src_p->size; i++) {
			    over_src[src_p->size-(i+1)] = s[i];
			}
		    } else {
			for (i=0; i<src_p->size; i++) {
			    over_src[i] = s[i];
			}
		    }
		    if ((H5T_overflow_g)(src_id, dst_id, over_src, d)>=0) {
			goto next;
		    }
		}
		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; i<half_size; i++) {
		    uint8_t tmp = d[dst_p->size-(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.
	     */
	next:
	    if (d==dbuf) HDmemcpy (dp, d, dst_p->size);
	    if (stride) {
		sp += direction * stride;
		dp += direction * stride;
	    } else {
		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_s_s
 *
 * Purpose:	Convert one fixed-length string type to another.
 *
 * Return:	Non-negative on success/Negative on failure
 *
 * Programmer:	Robb Matzke
 *		Friday, August	7, 1998
 *
 * Modifications:
 *		Robb Matzke, 1999-06-16
 *		Added support for non-zero strides. If STRIDE is non-zero
 *		then convert one value at each memory location advancing
 *		STRIDE bytes each time; otherwise assume both source and
 *		destination values are packed.
 *-------------------------------------------------------------------------
 */
herr_t
H5T_conv_s_s (hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata, size_t nelmts,
	      size_t stride, void *buf, void UNUSED *bkg, hid_t UNUSED dset_xfer_plist)
{
    H5T_t	*src=NULL;		/*source data type		*/
    H5T_t	*dst=NULL;		/*destination data type		*/
    intn	direction;		/*direction of traversal	*/
    size_t	elmtno;			/*element number		*/
    size_t	olap;			/*num overlapping elements	*/
    size_t	nchars=0;		/*number of characters copied	*/
    uint8_t	*s, *sp, *d, *dp;	/*src and dst traversal pointers*/
    uint8_t	*dbuf=NULL;		/*temp buf for overlap convers.	*/
    herr_t	ret_value=FAIL;		/*return value			*/
    
    FUNC_ENTER(H5T_conv_s_s, FAIL);

    switch (cdata->command) {
    case H5T_CONV_INIT:
	if (H5I_DATATYPE!=H5I_get_type(src_id) ||
	    NULL==(src=H5I_object(src_id)) ||
	    H5I_DATATYPE!=H5I_get_type(dst_id) ||
	    NULL==(dst=H5I_object(dst_id))) {
	    HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a data type");
	}
	if (8*src->size != src->u.atomic.prec ||
	    8*dst->size != dst->u.atomic.prec) {
	    HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "bad precision");
	}
	if (0 != src->u.atomic.offset ||
	    0 != dst->u.atomic.offset) {
	    HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "bad offset");
	}
	if (H5T_CSET_ASCII != src->u.atomic.u.s.cset ||
	    H5T_CSET_ASCII != dst->u.atomic.u.s.cset) {
	    HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "bad character set");
	}
	if (src->u.atomic.u.s.pad<0 || src->u.atomic.u.s.pad>=H5T_NPAD ||
	    dst->u.atomic.u.s.pad<0 || dst->u.atomic.u.s.pad>=H5T_NPAD) {
	    HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "bad character padding");
	}
	cdata->need_bkg = H5T_BKG_NO;
	break;

    case H5T_CONV_FREE:
	break;

    case H5T_CONV_CONV:
	/* Get the data types */
	if (H5I_DATATYPE!=H5I_get_type(src_id) ||
	    NULL==(src=H5I_object(src_id)) ||
	    H5I_DATATYPE!=H5I_get_type(dst_id) ||
	    NULL==(dst=H5I_object(dst_id))) {
	    HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a data type");
	}

	/*
	 * 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->size==dst->size || stride) {
	    /*
	     * When the source and destination are the same size we can do
	     * all the conversions in place.
	     */
	    sp = dp = (uint8_t*)buf;
	    direction = 1;
	    olap = 0;
	} else if (src->size>=dst->size) {
	    double olapd = HDceil((double)(dst->size)/
				  (double)(src->size-dst->size));
	    olap = (size_t)olapd;
	    sp = dp = (uint8_t*)buf;
	    direction = 1;
	} else {
	    double olapd = HDceil((double)(src->size)/
				  (double)(dst->size-src->size));
	    olap = (size_t)olapd;
	    sp = (uint8_t*)buf + (nelmts-1) * src->size;
	    dp = (uint8_t*)buf + (nelmts-1) * dst->size;
	    direction = -1;
	}

	/* Allocate the overlap buffer */
	if (NULL==(dbuf=H5MM_malloc(dst->size))) {
	    HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL,
			"memory allocation failed for string conversion");
	}
	
	/* The conversion loop. */
	for (elmtno=0; elmtno<nelmts; elmtno++) {

	    /*
	     * If the source and destination buffers overlap then use a
	     * temporary buffer for the destination.
	     */
	    if (direction>0) {
		s = sp;
		d = elmtno<olap ? dbuf : dp;
	    } else {
		s = sp;
		d = elmtno+olap >= nelmts ? dbuf : dp;
	    }
#ifndef NDEBUG
	    /* I don't quite trust the overlap calculations yet --rpm */
	    if (src->size==dst->size || stride) {
		assert(s==d);
	    } else if (d==dbuf) {
		assert((dp>=sp && dp<sp+src->size) ||
		       (sp>=dp && sp<dp+dst->size));
	    } else {
		assert((dp<sp && dp+dst->size<=sp) ||
		       (sp<dp && sp+src->size<=dp));
	    }
#endif
	    
	    /* Copy characters from source to destination */
	    switch (src->u.atomic.u.s.pad) {
	    case H5T_STR_NULLTERM:
		for (nchars=0;
		     nchars<dst->size && nchars<src->size && s[nchars];
		     nchars++) {
		    d[nchars] = s[nchars];
		}
		break;

	    case H5T_STR_NULLPAD:
		for (nchars=0;
		     nchars<dst->size && nchars<src->size && s[nchars];
		     nchars++) {
		    d[nchars] = s[nchars];
		}
		break;

	    case H5T_STR_SPACEPAD:
		nchars = src->size;
		while (nchars>0 && ' '==s[nchars-1]) --nchars;
		nchars = MIN(dst->size, nchars);
		HDmemcpy(d, s, nchars);
		break;

	    case H5T_STR_RESERVED_3:
	    case H5T_STR_RESERVED_4:
	    case H5T_STR_RESERVED_5:
	    case H5T_STR_RESERVED_6:
	    case H5T_STR_RESERVED_7:
	    case H5T_STR_RESERVED_8:
	    case H5T_STR_RESERVED_9:
	    case H5T_STR_RESERVED_10:
	    case H5T_STR_RESERVED_11:
	    case H5T_STR_RESERVED_12:
	    case H5T_STR_RESERVED_13:
	    case H5T_STR_RESERVED_14:
	    case H5T_STR_RESERVED_15:
	    case H5T_STR_ERROR:
		HGOTO_ERROR(H5E_DATATYPE, H5E_UNSUPPORTED, FAIL,
			    "source string padding method not supported");
	    }

	    /* Terminate or pad the destination */
	    switch (dst->u.atomic.u.s.pad) {
	    case H5T_STR_NULLTERM:
		while (nchars<dst->size) d[nchars++] = '\0';
		d[dst->size-1] = '\0';
		break;
		
	    case H5T_STR_NULLPAD:
		while (nchars<dst->size) d[nchars++] = '\0';
		break;
		
	    case H5T_STR_SPACEPAD:
		while (nchars<dst->size) d[nchars++] = ' ';
		break;

	    case H5T_STR_RESERVED_3:
	    case H5T_STR_RESERVED_4:
	    case H5T_STR_RESERVED_5:
	    case H5T_STR_RESERVED_6:
	    case H5T_STR_RESERVED_7:
	    case H5T_STR_RESERVED_8:
	    case H5T_STR_RESERVED_9:
	    case H5T_STR_RESERVED_10:
	    case H5T_STR_RESERVED_11:
	    case H5T_STR_RESERVED_12:
	    case H5T_STR_RESERVED_13:
	    case H5T_STR_RESERVED_14:
	    case H5T_STR_RESERVED_15:
	    case H5T_STR_ERROR:
		HGOTO_ERROR(H5E_DATATYPE, H5E_UNSUPPORTED, FAIL,
			    "destination string padding method not supported");
	    }

	    /*
	     * If we 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->size);
	    if (stride) {
		sp += direction * stride;
		dp += direction * stride;
	    } else {
		sp += direction * src->size;
		dp += direction * dst->size;
	    }
	}
	break;

    default:
	HGOTO_ERROR(H5E_DATATYPE, H5E_UNSUPPORTED, FAIL,
		      "unknown converson command");
    }
    ret_value = SUCCEED;

 done:
    H5MM_xfree(dbuf);
    FUNC_LEAVE(ret_value);
}


/*-------------------------------------------------------------------------
 * Function:	H5T_conv_schar_uchar
 *
 * Purpose:	Converts `signed char' to `unsigned char'
 *
 * Return:	Success:	non-negative
 *
 *		Failure:	negative
 *
 * Programmer:	Robb Matzke
 *		Monday, November 16, 1998
 *
 * Modifications:
 *
 *-------------------------------------------------------------------------
 */
herr_t
H5T_conv_schar_uchar(hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata,
		     size_t nelmts, size_t stride, void *buf, void UNUSED *bkg, hid_t UNUSED dset_xfer_plist)
{
    FUNC_ENTER(H5T_conv_schar_uchar, FAIL);
    H5T_CONV_su(SCHAR, UCHAR,
		signed char, unsigned char);
    FUNC_LEAVE(SUCCEED);
}


/*-------------------------------------------------------------------------
 * Function:	H5T_conv_uchar_schar
 *
 * Purpose:	Converts `unsigned char' to `signed char'
 *
 * Return:	Success:	non-negative
 *
 *		Failure:	negative
 *
 * Programmer:	Robb Matzke
 *		Monday, November 16, 1998
 *
 * Modifications:
 *
 *-------------------------------------------------------------------------
 */
herr_t
H5T_conv_uchar_schar(hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata,
		     size_t nelmts, size_t stride, void *buf, void UNUSED *bkg, hid_t UNUSED dset_xfer_plist)
{
    FUNC_ENTER(H5T_conv_uchar_schar, FAIL);
    H5T_CONV_us(UCHAR, SCHAR,
		unsigned char, signed char,
		SCHAR_MAX);
    FUNC_LEAVE(SUCCEED);
}


/*-------------------------------------------------------------------------
 * Function:	H5T_conv_schar_short
 *
 * Purpose:	Converts `signed char' to `short'
 *
 * Return:	Success:	Non-negative
 *
 *		Failure:	Negative
 *
 * Programmer:	Robb Matzke
 *		Friday, November 13, 1998
 *
 * Modifications:
 *
 *-------------------------------------------------------------------------
 */
herr_t
H5T_conv_schar_short(hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata,
		     size_t nelmts, size_t stride, void *buf, void UNUSED *bkg, hid_t UNUSED dset_xfer_plist)
{
    FUNC_ENTER(H5T_conv_schar_short, FAIL);
    H5T_CONV_sS(SCHAR, SHORT,
		signed char, short);
    FUNC_LEAVE(SUCCEED);
}


/*-------------------------------------------------------------------------
 * Function:	H5T_conv_schar_ushort
 *
 * Purpose:	Converts `signed char' to `unsigned short'
 *
 * Return:	Success:	Non-negative
 *
 *		Failure:	Negative
 *
 * Programmer:	Robb Matzke
 *		Friday, November 13, 1998
 *
 * Modifications:
 *
 *-------------------------------------------------------------------------
 */
herr_t
H5T_conv_schar_ushort(hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata,
		      size_t nelmts, size_t stride, void *buf,
		      void UNUSED *bkg, hid_t UNUSED dset_xfer_plist)
{
    FUNC_ENTER(H5T_conv_schar_ushort, FAIL);
    H5T_CONV_sU(SCHAR, USHORT,
		signed char, unsigned short);
    FUNC_LEAVE(SUCCEED);
}


/*-------------------------------------------------------------------------
 * Function:	H5T_conv_uchar_short
 *
 * Purpose:	Converts `unsigned char' to `short'
 *
 * Return:	Success:	non-negative
 *
 *		Failure:	negative
 *
 * Programmer:	Robb Matzke
 *		Friday, November 13, 1998
 *
 * Modifications:
 *
 *-------------------------------------------------------------------------
 */
herr_t
H5T_conv_uchar_short(hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata,
		     size_t nelmts, size_t stride, void *buf, void UNUSED *bkg, hid_t UNUSED dset_xfer_plist)
{
    FUNC_ENTER(H5T_conv_uchar_short, FAIL);
    H5T_CONV_uS(UCHAR, SHORT,
		unsigned char, short,
		SHRT_MAX);
    FUNC_LEAVE(SUCCEED);
}


/*-------------------------------------------------------------------------
 * Function:	H5T_conv_uchar_ushort
 *
 * Purpose:	Converts `unsigned char' to `unsigned short'
 *
 * Return:	Success:	non-negative
 *
 *		Failure:	negative
 *
 * Programmer:	Robb Matzke
 *		Friday, November 13, 1998
 *
 * Modifications:
 *
 *-------------------------------------------------------------------------
 */
herr_t
H5T_conv_uchar_ushort(hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata,
		      size_t nelmts, size_t stride, void *buf,
		      void UNUSED *bkg, hid_t UNUSED dset_xfer_plist)
{
    FUNC_ENTER(H5T_conv_uchar_ushort, FAIL);
    H5T_CONV_uU(UCHAR, USHORT,
		unsigned char, unsigned short);
    FUNC_LEAVE(SUCCEED);
}


/*-------------------------------------------------------------------------
 * Function:	H5T_conv_schar_int
 *
 * Purpose:	Converts `signed char' to `int'
 *
 * Return:	Success:	Non-negative
 *
 *		Failure:	Negative
 *
 * Programmer:	Robb Matzke
 *		Friday, November 13, 1998
 *
 * Modifications:
 *
 *-------------------------------------------------------------------------
 */
herr_t
H5T_conv_schar_int(hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata,
		   size_t nelmts, size_t stride, void *buf, void UNUSED *bkg, hid_t UNUSED dset_xfer_plist)
{
    FUNC_ENTER(H5T_conv_schar_int, FAIL);
    H5T_CONV_sS(SCHAR, INT,
		signed char, int);
    FUNC_LEAVE(SUCCEED);
}


/*-------------------------------------------------------------------------
 * Function:	H5T_conv_schar_uint
 *
 * Purpose:	Converts `signed char' to `unsigned int'
 *
 * Return:	Success:	Non-negative
 *
 *		Failure:	Negative
 *
 * Programmer:	Robb Matzke
 *		Friday, November 13, 1998
 *
 * Modifications:
 *
 *-------------------------------------------------------------------------
 */
herr_t
H5T_conv_schar_uint(hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata,
		    size_t nelmts, size_t stride, void *buf, void UNUSED *bkg, hid_t UNUSED dset_xfer_plist)
{
    FUNC_ENTER(H5T_conv_schar_uint, FAIL);
    H5T_CONV_sU(SCHAR, UINT,
		signed char, unsigned);
    FUNC_LEAVE(SUCCEED);
}


/*-------------------------------------------------------------------------
 * Function:	H5T_conv_uchar_int
 *
 * Purpose:	Converts `unsigned char' to `int'
 *
 * Return:	Success:	Non-negative
 *
 *		Failure:	Negative
 *
 * Programmer:	Robb Matzke
 *		Friday, November 13, 1998
 *
 * Modifications:
 *
 *-------------------------------------------------------------------------
 */
herr_t
H5T_conv_uchar_int(hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata,
		   size_t nelmts, size_t stride, void *buf, void UNUSED *bkg, hid_t UNUSED dset_xfer_plist)
{
    FUNC_ENTER(H5T_conv_uchar_int, FAIL);
    H5T_CONV_uS(UCHAR, INT,
		unsigned char, int,
		INT_MAX);
    FUNC_LEAVE(SUCCEED);
}


/*-------------------------------------------------------------------------
 * Function:	H5T_conv_uchar_uint
 *
 * Purpose:	Converts `unsigned char' to `unsigned int'
 *
 * Return:	Success:	Non-negative
 *
 *		Failure:	Negative
 *
 * Programmer:	Robb Matzke
 *		Friday, November 13, 1998
 *
 * Modifications:
 *
 *-------------------------------------------------------------------------
 */
herr_t
H5T_conv_uchar_uint(hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata,
		    size_t nelmts, size_t stride, void *buf, void UNUSED *bkg, hid_t UNUSED dset_xfer_plist)
{
    FUNC_ENTER(H5T_conv_uchar_uint, FAIL);
    H5T_CONV_uU(UCHAR, UINT,
		unsigned char, unsigned);
    FUNC_LEAVE(SUCCEED);
}


/*-------------------------------------------------------------------------
 * Function:	H5T_conv_schar_long
 *
 * Purpose:	Converts `signed char' to `long'
 *
 * Return:	Success:	Non-negative
 *
 *		Failure:	Negative
 *
 * Programmer:	Robb Matzke
 *		Friday, November 13, 1998
 *
 * Modifications:
 *
 *-------------------------------------------------------------------------
 */
herr_t
H5T_conv_schar_long(hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata,
		    size_t nelmts, size_t stride, void *buf, void UNUSED *bkg, hid_t UNUSED dset_xfer_plist)
{
    FUNC_ENTER(H5T_conv_schar_long, FAIL);
    H5T_CONV_sS(SCHAR, LONG,
		signed char, long);
    FUNC_LEAVE(SUCCEED);
}


/*-------------------------------------------------------------------------
 * Function:	H5T_conv_schar_ulong
 *
 * Purpose:	Converts `signed char' to `unsigned long'
 *
 * Return:	Success:	Non-negative
 *
 *		Failure:	Negative
 *
 * Programmer:	Robb Matzke
 *		Friday, November 13, 1998
 *
 * Modifications:
 *
 *-------------------------------------------------------------------------
 */
herr_t
H5T_conv_schar_ulong(hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata,
		     size_t nelmts, size_t stride, void *buf, void UNUSED *bkg, hid_t UNUSED dset_xfer_plist)
{
    FUNC_ENTER(H5T_conv_schar_ulong, FAIL);
    H5T_CONV_sU(SCHAR, ULONG,
		signed char, unsigned long);
    FUNC_LEAVE(SUCCEED);
}


/*-------------------------------------------------------------------------
 * Function:	H5T_conv_uchar_long
 *
 * Purpose:	Converts `unsigned char' to `long'
 *
 * Return:	Success:	Non-negative
 *
 *		Failure:	Negative
 *
 * Programmer:	Robb Matzke
 *		Friday, November 13, 1998
 *
 * Modifications:
 *
 *-------------------------------------------------------------------------
 */
herr_t
H5T_conv_uchar_long(hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata,
		    size_t nelmts, size_t stride, void *buf, void UNUSED *bkg, hid_t UNUSED dset_xfer_plist)
{
    FUNC_ENTER(H5T_conv_uchar_long, FAIL);
    H5T_CONV_uS(UCHAR, LONG,
		unsigned char, long,
		LONG_MAX);
    FUNC_LEAVE(SUCCEED);
}


/*-------------------------------------------------------------------------
 * Function:	H5T_conv_uchar_ulong
 *
 * Purpose:	Converts `unsigned char' to `unsigned long'
 *
 * Return:	Success:	Non-negative
 *
 *		Failure:	Negative
 *
 * Programmer:	Robb Matzke
 *		Friday, November 13, 1998
 *
 * Modifications:
 *
 *-------------------------------------------------------------------------
 */
herr_t
H5T_conv_uchar_ulong(hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata,
		     size_t nelmts, size_t stride, void *buf, void UNUSED *bkg, hid_t UNUSED dset_xfer_plist)
{
    FUNC_ENTER(H5T_conv_uchar_ulong, FAIL);
    H5T_CONV_uU(UCHAR, ULONG,
		unsigned char, unsigned long);
    FUNC_LEAVE(SUCCEED);
}


/*-------------------------------------------------------------------------
 * Function:	H5T_conv_schar_llong
 *
 * Purpose:	Converts `signed char' to `long_long'
 *
 * Return:	Success:	Non-negative
 *
 *		Failure:	Negative
 *
 * Programmer:	Robb Matzke
 *		Friday, November 13, 1998
 *
 * Modifications:
 *
 *-------------------------------------------------------------------------
 */
herr_t
H5T_conv_schar_llong(hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata,
		     size_t nelmts, size_t stride, void *buf, void UNUSED *bkg, hid_t UNUSED dset_xfer_plist)
{
    FUNC_ENTER(H5T_conv_schar_llong, FAIL);
    H5T_CONV_sS(SCHAR, LLONG,
		signed char, long_long);
    FUNC_LEAVE(SUCCEED);
}


/*-------------------------------------------------------------------------
 * Function:	H5T_conv_schar_ullong
 *
 * Purpose:	Converts `signed char' to `unsigned long_long'
 *
 * Return:	Success:	Non-negative
 *
 *		Failure:	Negative
 *
 * Programmer:	Robb Matzke
 *		Friday, November 13, 1998
 *
 * Modifications:
 *
 *-------------------------------------------------------------------------
 */
herr_t
H5T_conv_schar_ullong(hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata,
		      size_t nelmts, size_t stride, void *buf,
		      void UNUSED *bkg, hid_t UNUSED dset_xfer_plist)
{
    FUNC_ENTER(H5T_conv_schar_ullong, FAIL);
    H5T_CONV_sU(SCHAR, ULLONG,
		signed char, unsigned long_long);
    FUNC_LEAVE(SUCCEED);
}


/*-------------------------------------------------------------------------
 * Function:	H5T_conv_uchar_llong
 *
 * Purpose:	Converts `unsigned char' to `long_long'
 *
 * Return:	Success:	Non-negative
 *
 *		Failure:	Negative
 *
 * Programmer:	Robb Matzke
 *		Friday, November 13, 1998
 *
 * Modifications:
 *
 *-------------------------------------------------------------------------
 */
herr_t
H5T_conv_uchar_llong(hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata,
		     size_t nelmts, size_t stride, void *buf, void UNUSED *bkg, hid_t UNUSED dset_xfer_plist)
{
    FUNC_ENTER(H5T_conv_uchar_llong, FAIL);
    H5T_CONV_uS(UCHAR, LLONG,
		unsigned char, long_long,
		LLONG_MAX);
    FUNC_LEAVE(SUCCEED);
}


/*-------------------------------------------------------------------------
 * Function:	H5T_conv_uchar_ullong
 *
 * Purpose:	Converts `unsigned char' to `unsigned long_long'
 *
 * Return:	Success:	Non-negative
 *
 *		Failure:	Negative
 *
 * Programmer:	Robb Matzke
 *		Friday, November 13, 1998
 *
 * Modifications:
 *
 *-------------------------------------------------------------------------
 */
herr_t
H5T_conv_uchar_ullong(hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata,
		      size_t nelmts, size_t stride, void *buf,
		      void UNUSED *bkg, hid_t UNUSED dset_xfer_plist)
{
    FUNC_ENTER(H5T_conv_uchar_ullong, FAIL);
    H5T_CONV_uU(UCHAR, ULLONG,
		unsigned char, unsigned long_long);
    FUNC_LEAVE(SUCCEED);
}


/*-------------------------------------------------------------------------
 * Function:	H5T_conv_short_schar
 *
 * Purpose:	Converts `short' to `signed char'
 *
 * Return:	Success:	non-negative
 *
 *		Failure:	negative
 *
 * Programmer:	Robb Matzke
 *		Friday, November 13, 1998
 *
 * Modifications:
 *
 *-------------------------------------------------------------------------
 */
herr_t
H5T_conv_short_schar(hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata,
		     size_t nelmts, size_t stride, void *buf, void UNUSED *bkg, hid_t UNUSED dset_xfer_plist)
{
    FUNC_ENTER(H5T_conv_short_schar, FAIL);
    H5T_CONV_Ss(SHORT, SCHAR,
		short, signed char,
		SCHAR_MIN, SCHAR_MAX);
    FUNC_LEAVE(SUCCEED);
}


/*-------------------------------------------------------------------------
 * Function:	H5T_conv_short_uchar
 *
 * Purpose:	Converts `short' to `unsigned char'
 *
 * Return:	Success:	non-negative
 *
 *		Failure:	negative
 *
 * Programmer:	Robb Matzke
 *		Friday, November 13, 1998
 *
 * Modifications:
 *
 *-------------------------------------------------------------------------
 */
herr_t
H5T_conv_short_uchar(hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata,
		     size_t nelmts, size_t stride, void *buf, void UNUSED *bkg, hid_t UNUSED dset_xfer_plist)
{
    FUNC_ENTER(H5T_conv_short_uchar, FAIL);
    H5T_CONV_Su(SHORT, UCHAR,
		short, unsigned char,
		UCHAR_MAX);
    FUNC_LEAVE(SUCCEED);
}


/*-------------------------------------------------------------------------
 * Function:	H5T_conv_ushort_schar
 *
 * Purpose:	Converts `unsigned short' to `signed char'
 *
 * Return:	Success:	non-negative
 *
 *		Failure:	negative
 *
 * Programmer:	Robb Matzke
 *		Friday, November 13, 1998
 *
 * Modifications:
 *
 *-------------------------------------------------------------------------
 */
herr_t
H5T_conv_ushort_schar(hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata,
		      size_t nelmts, size_t stride, void *buf,
		      void UNUSED *bkg, hid_t UNUSED dset_xfer_plist)
{
    FUNC_ENTER(H5T_conv_ushort_schar, FAIL);
    H5T_CONV_Us(USHORT, SCHAR,
		unsigned short, signed char,
		SCHAR_MAX);
    FUNC_LEAVE(SUCCEED);
}


/*-------------------------------------------------------------------------
 * Function:	H5T_conv_ushort_uchar
 *
 * Purpose:	Converts `unsigned short' to `unsigned char'
 *
 * Return:	Success:	non-negative
 *
 *		Failure:	negative
 *
 * Programmer:	Robb Matzke
 *		Friday, November 13, 1998
 *
 * Modifications:
 *
 *-------------------------------------------------------------------------
 */
herr_t
H5T_conv_ushort_uchar(hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata,
		      size_t nelmts, size_t stride, void *buf,
		      void UNUSED *bkg, hid_t UNUSED dset_xfer_plist)
{
    FUNC_ENTER(H5T_conv_ushort_uchar, FAIL);
    H5T_CONV_Uu(USHORT, UCHAR,
		unsigned short, unsigned char,
		UCHAR_MAX);
    FUNC_LEAVE(SUCCEED);
}


/*-------------------------------------------------------------------------
 * Function:	H5T_conv_short_ushort
 *
 * Purpose:	Converts `short' to `unsigned short'
 *
 * Return:	Success:	non-negative
 *
 *		Failure:	negative
 *
 * Programmer:	Robb Matzke
 *		Monday, November 16, 1998
 *
 * Modifications:
 *
 *-------------------------------------------------------------------------
 */
herr_t
H5T_conv_short_ushort(hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata,
		      size_t nelmts, size_t stride, void *buf,
		      void UNUSED *bkg, hid_t UNUSED dset_xfer_plist)
{
    FUNC_ENTER(H5T_conv_short_ushort, FAIL);
    H5T_CONV_su(SHORT, USHORT,
		short, unsigned short);
    FUNC_LEAVE(SUCCEED);
}


/*-------------------------------------------------------------------------
 * Function:	H5T_conv_ushort_short
 *
 * Purpose:	Converts `unsigned short' to `short'
 *
 * Return:	Success:	non-negative
 *
 *		Failure:	negative
 *
 * Programmer:	Robb Matzke
 *		Monday, November 16, 1998
 *
 * Modifications:
 *
 *-------------------------------------------------------------------------
 */
herr_t
H5T_conv_ushort_short(hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata,
		      size_t nelmts, size_t stride, void *buf,
		      void UNUSED *bkg, hid_t UNUSED dset_xfer_plist)
{
    FUNC_ENTER(H5T_conv_ushort_short, FAIL);
    H5T_CONV_us(USHORT, SHORT,
		unsigned short, short,
		SHRT_MAX);
    FUNC_LEAVE(SUCCEED);
}


/*-------------------------------------------------------------------------
 * Function:	H5T_conv_short_int
 *
 * Purpose:	Converts `short' to `int'
 *
 * Return:	Success:	non-negative
 *
 *		Failure:	negative
 *
 * Programmer:	Robb Matzke
 *		Friday, November 13, 1998
 *
 * Modifications:
 *
 *-------------------------------------------------------------------------
 */
herr_t
H5T_conv_short_int(hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata,
		   size_t nelmts, size_t stride, void *buf, void UNUSED *bkg, hid_t UNUSED dset_xfer_plist)
{
    FUNC_ENTER(H5T_conv_short_int, FAIL);
    H5T_CONV_sS(SHORT, INT,
		short, int);
    FUNC_LEAVE(SUCCEED);
}


/*-------------------------------------------------------------------------
 * Function:	H5T_conv_short_uint
 *
 * Purpose:	Converts `short' to `unsigned int'
 *
 * Return:	Success:	Non-negative
 *
 *		Failure:	Negative
 *
 * Programmer:	Robb Matzke
 *		Friday, November 13, 1998
 *
 * Modifications:
 *
 *-------------------------------------------------------------------------
 */
herr_t
H5T_conv_short_uint(hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata,
		    size_t nelmts, size_t stride, void *buf, void UNUSED *bkg, hid_t UNUSED dset_xfer_plist)
{
    FUNC_ENTER(H5T_conv_short_uint, FAIL);
    H5T_CONV_sU(SHORT, UINT,
		short, unsigned);
    FUNC_LEAVE(SUCCEED);
}


/*-------------------------------------------------------------------------
 * Function:	H5T_conv_ushort_int
 *
 * Purpose:	Converts `unsigned short' to `int'
 *
 * Return:	Success:	Non-negative
 *
 *		Failure:	Negative
 *
 * Programmer:	Robb Matzke
 *		Friday, November 13, 1998
 *
 * Modifications:
 *
 *-------------------------------------------------------------------------
 */
herr_t
H5T_conv_ushort_int(hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata,
		    size_t nelmts, size_t stride, void *buf, void UNUSED *bkg, hid_t UNUSED dset_xfer_plist)
{
    FUNC_ENTER(H5T_conv_ushort_int, FAIL);
    H5T_CONV_uS(USHORT, INT,
		unsigned short, int,
		INT_MAX);
    FUNC_LEAVE(SUCCEED);
}


/*-------------------------------------------------------------------------
 * Function:	H5T_conv_ushort_uint
 *
 * Purpose:	Converts `unsigned short' to `unsigned int'
 *
 * Return:	Success:	non-negative
 *
 *		Failure:	negative
 *
 * Programmer:	Robb Matzke
 *		Friday, November 13, 1998
 *
 * Modifications:
 *
 *-------------------------------------------------------------------------
 */
herr_t
H5T_conv_ushort_uint(hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata,
		     size_t nelmts, size_t stride, void *buf, void UNUSED *bkg, hid_t UNUSED dset_xfer_plist)
{
    FUNC_ENTER(H5T_conv_ushort_uint, FAIL);
    H5T_CONV_uU(USHORT, UINT,
		unsigned short, unsigned);
    FUNC_LEAVE(SUCCEED);
}


/*-------------------------------------------------------------------------
 * Function:	H5T_conv_short_long
 *
 * Purpose:	Converts `short' to `long'
 *
 * Return:	Success:	non-negative
 *
 *		Failure:	negative
 *
 * Programmer:	Robb Matzke
 *		Friday, November 13, 1998
 *
 * Modifications:
 *
 *-------------------------------------------------------------------------
 */
herr_t
H5T_conv_short_long(hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata,
		    size_t nelmts, size_t stride, void *buf, void UNUSED *bkg, hid_t UNUSED dset_xfer_plist)
{
    FUNC_ENTER(H5T_conv_short_long, FAIL);
    H5T_CONV_sS(SHORT, LONG,
		short, long);
    FUNC_LEAVE(SUCCEED);
}


/*-------------------------------------------------------------------------
 * Function:	H5T_conv_short_ulong
 *
 * Purpose:	Converts `short' to `unsigned long'
 *
 * Return:	Success:	Non-negative
 *
 *		Failure:	Negative
 *
 * Programmer:	Robb Matzke
 *		Friday, November 13, 1998
 *
 * Modifications:
 *
 *-------------------------------------------------------------------------
 */
herr_t
H5T_conv_short_ulong(hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata,
		     size_t nelmts, size_t stride, void *buf, void UNUSED *bkg, hid_t UNUSED dset_xfer_plist)
{
    FUNC_ENTER(H5T_conv_short_ulong, FAIL);
    H5T_CONV_sU(SHORT, ULONG,
		short, unsigned long);
    FUNC_LEAVE(SUCCEED);
}


/*-------------------------------------------------------------------------
 * Function:	H5T_conv_ushort_long
 *
 * Purpose:	Converts `unsigned short' to `long'
 *
 * Return:	Success:	Non-negative
 *
 *		Failure:	Negative
 *
 * Programmer:	Robb Matzke
 *		Friday, November 13, 1998
 *
 * Modifications:
 *
 *-------------------------------------------------------------------------
 */
herr_t
H5T_conv_ushort_long(hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata,
		     size_t nelmts, size_t stride, void *buf, void UNUSED *bkg, hid_t UNUSED dset_xfer_plist)
{
    FUNC_ENTER(H5T_conv_ushort_long, FAIL);
    H5T_CONV_uS(USHORT, LONG,
		unsigned short, long,
		LONG_MAX);
    FUNC_LEAVE(SUCCEED);
}


/*-------------------------------------------------------------------------
 * Function:	H5T_conv_ushort_ulong
 *
 * Purpose:	Converts `unsigned short' to `unsigned long'
 *
 * Return:	Success:	non-negative
 *
 *		Failure:	negative
 *
 * Programmer:	Robb Matzke
 *		Friday, November 13, 1998
 *
 * Modifications:
 *
 *-------------------------------------------------------------------------
 */
herr_t
H5T_conv_ushort_ulong(hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata,
		      size_t nelmts, size_t stride, void *buf,
		      void UNUSED *bkg, hid_t UNUSED dset_xfer_plist)
{
    FUNC_ENTER(H5T_conv_ushort_ulong, FAIL);
    H5T_CONV_uU(USHORT, ULONG,
		unsigned short, unsigned long);
    FUNC_LEAVE(SUCCEED);
}


/*-------------------------------------------------------------------------
 * Function:	H5T_conv_short_llong
 *
 * Purpose:	Converts `short' to `long_long'
 *
 * Return:	Success:	Non-negative
 *
 *		Failure:	Negative
 *
 * Programmer:	Robb Matzke
 *		Friday, November 13, 1998
 *
 * Modifications:
 *
 *-------------------------------------------------------------------------
 */
herr_t
H5T_conv_short_llong(hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata,
		     size_t nelmts, size_t stride, void *buf, void UNUSED *bkg, hid_t UNUSED dset_xfer_plist)
{
    FUNC_ENTER(H5T_conv_short_llong, FAIL);
    H5T_CONV_sS(SHORT, LLONG,
		short, long_long);
    FUNC_LEAVE(SUCCEED);
}


/*-------------------------------------------------------------------------
 * Function:	H5T_conv_short_ullong
 *
 * Purpose:	Converts `short' to `unsigned long_long'
 *
 * Return:	Success:	Non-negative
 *
 *		Failure:	Negative
 *
 * Programmer:	Robb Matzke
 *		Friday, November 13, 1998
 *
 * Modifications:
 *
 *-------------------------------------------------------------------------
 */
herr_t
H5T_conv_short_ullong(hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata,
		      size_t nelmts, size_t stride, void *buf,
		      void UNUSED *bkg, hid_t UNUSED dset_xfer_plist)
{
    FUNC_ENTER(H5T_conv_short_ullong, FAIL);
    H5T_CONV_sU(SHORT, ULLONG,
		short, unsigned long_long);
    FUNC_LEAVE(SUCCEED);
}


/*-------------------------------------------------------------------------
 * Function:	H5T_conv_ushort_llong
 *
 * Purpose:	Converts `unsigned short' to `long_long'
 *
 * Return:	Success:	Non-negative
 *
 *		Failure:	Negative
 *
 * Programmer:	Robb Matzke
 *		Friday, November 13, 1998
 *
 * Modifications:
 *
 *-------------------------------------------------------------------------
 */
herr_t
H5T_conv_ushort_llong(hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata,
		      size_t nelmts, size_t stride, void *buf,
		      void UNUSED *bkg, hid_t UNUSED dset_xfer_plist)
{
    FUNC_ENTER(H5T_conv_ushort_llong, FAIL);
    H5T_CONV_uS(USHORT, LLONG,
		unsigned short, long_long,
		LLONG_MAX);
    FUNC_LEAVE(SUCCEED);
}


/*-------------------------------------------------------------------------
 * Function:	H5T_conv_ushort_ullong
 *
 * Purpose:	Converts `unsigned short' to `unsigned long_long'
 *
 * Return:	Success:	Non-negative
 *
 *		Failure:	Negative
 *
 * Programmer:	Robb Matzke
 *		Friday, November 13, 1998
 *
 * Modifications:
 *
 *-------------------------------------------------------------------------
 */
herr_t
H5T_conv_ushort_ullong(hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata,
		       size_t nelmts, size_t stride, void *buf,
		       void UNUSED *bkg, hid_t UNUSED dset_xfer_plist)
{
    FUNC_ENTER(H5T_conv_ushort_ullong, FAIL);
    H5T_CONV_uU(USHORT, ULLONG,
		unsigned short, unsigned long_long);
    FUNC_LEAVE(SUCCEED);
}


/*-------------------------------------------------------------------------
 * Function:	H5T_conv_int_schar
 *
 * Purpose:	Converts `int' to `signed char'
 *
 * Return:	Success:	non-negative
 *
 *		Failure:	negative
 *
 * Programmer:	Robb Matzke
 *		Friday, November 13, 1998
 *
 * Modifications:
 *
 *-------------------------------------------------------------------------
 */
herr_t
H5T_conv_int_schar(hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata,
		   size_t nelmts, size_t stride, void *buf, void UNUSED *bkg, hid_t UNUSED dset_xfer_plist)
{
    FUNC_ENTER(H5T_conv_int_schar, FAIL);
    H5T_CONV_Ss(INT, SCHAR,
		int, signed char,
		SCHAR_MIN, SCHAR_MAX);
    FUNC_LEAVE(SUCCEED);
}


/*-------------------------------------------------------------------------
 * Function:	H5T_conv_int_uchar
 *
 * Purpose:	Converts `int' to `unsigned char'
 *
 * Return:	Success:	non-negative
 *
 *		Failure:	negative
 *
 * Programmer:	Robb Matzke
 *		Friday, November 13, 1998
 *
 * Modifications:
 *
 *-------------------------------------------------------------------------
 */
herr_t
H5T_conv_int_uchar(hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata,
		   size_t nelmts, size_t stride, void *buf, void UNUSED *bkg, hid_t UNUSED dset_xfer_plist)
{
    FUNC_ENTER(H5T_conv_int_uchar, FAIL);
    H5T_CONV_Su(INT, UCHAR,
		int, unsigned char,
		UCHAR_MAX);
    FUNC_LEAVE(SUCCEED);
}


/*-------------------------------------------------------------------------
 * Function:	H5T_conv_uint_schar
 *
 * Purpose:	Converts `unsigned int' to `signed char'
 *
 * Return:	Success:	non-negative
 *
 *		Failure:	negative
 *
 * Programmer:	Robb Matzke
 *		Friday, November 13, 1998
 *
 * Modifications:
 *
 *-------------------------------------------------------------------------
 */
herr_t
H5T_conv_uint_schar(hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata,
		    size_t nelmts, size_t stride, void *buf, void UNUSED *bkg, hid_t UNUSED dset_xfer_plist)
{
    FUNC_ENTER(H5T_conv_uint_schar, FAIL);
    H5T_CONV_Us(UINT, SCHAR,
		unsigned, signed char,
		SCHAR_MAX);
    FUNC_LEAVE(SUCCEED);
}


/*-------------------------------------------------------------------------
 * Function:	H5T_conv_uint_uchar
 *
 * Purpose:	Converts `unsigned int' to `unsigned char'
 *
 * Return:	Success:	non-negative
 *
 *		Failure:	negative
 *
 * Programmer:	Robb Matzke
 *		Friday, November 13, 1998
 *
 * Modifications:
 *
 *-------------------------------------------------------------------------
 */
herr_t
H5T_conv_uint_uchar(hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata,
		    size_t nelmts, size_t stride, void *buf, void UNUSED *bkg, hid_t UNUSED dset_xfer_plist)
{
    FUNC_ENTER(H5T_conv_uint_uchar, FAIL);
    H5T_CONV_Uu(UINT, UCHAR,
		unsigned, unsigned char,
		UCHAR_MAX);
    FUNC_LEAVE(SUCCEED);
}


/*-------------------------------------------------------------------------
 * Function:	H5T_conv_int_short
 *
 * Purpose:	Converts `int' to `short'
 *
 * Return:	Success:	non-negative
 *
 *		Failure:	negative
 *
 * Programmer:	Robb Matzke
 *		Friday, November 13, 1998
 *
 * Modifications:
 *
 *-------------------------------------------------------------------------
 */
herr_t
H5T_conv_int_short(hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata,
		   size_t nelmts, size_t stride, void *buf, void UNUSED *bkg, hid_t UNUSED dset_xfer_plist)
{
    FUNC_ENTER(H5T_conv_int_short, FAIL);
    H5T_CONV_Ss(INT, SHORT,
		int, short,
		SHRT_MIN, SHRT_MAX);
    FUNC_LEAVE(SUCCEED);
}


/*-------------------------------------------------------------------------
 * Function:	H5T_conv_int_ushort
 *
 * Purpose:	Converts `int' to `unsigned short'
 *
 * Return:	Success:	non-negative
 *
 *		Failure:	negative
 *
 * Programmer:	Robb Matzke
 *		Friday, November 13, 1998
 *
 * Modifications:
 *
 *-------------------------------------------------------------------------
 */
herr_t
H5T_conv_int_ushort(hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata,
		    size_t nelmts, size_t stride, void *buf, void UNUSED *bkg, hid_t UNUSED dset_xfer_plist)
{
    FUNC_ENTER(H5T_conv_int_ushort, FAIL);
    H5T_CONV_Su(INT, USHORT,
		int, unsigned short,
		USHRT_MAX);
    FUNC_LEAVE(SUCCEED);
}


/*-------------------------------------------------------------------------
 * Function:	H5T_conv_uint_short
 *
 * Purpose:	Converts `unsigned int' to `short'
 *
 * Return:	Success:	non-negative
 *
 *		Failure:	negative
 *
 * Programmer:	Robb Matzke
 *		Friday, November 13, 1998
 *
 * Modifications:
 *
 *-------------------------------------------------------------------------
 */
herr_t
H5T_conv_uint_short(hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata,
		    size_t nelmts, size_t stride, void *buf, void UNUSED *bkg, hid_t UNUSED dset_xfer_plist)
{
    FUNC_ENTER(H5T_conv_uint_short, FAIL);
    H5T_CONV_Us(UINT, SHORT,
		unsigned, short,
		SHRT_MAX);
    FUNC_LEAVE(SUCCEED);
}


/*-------------------------------------------------------------------------
 * Function:	H5T_conv_uint_ushort
 *
 * Purpose:	Converts `unsigned int' to `unsigned short'
 *
 * Return:	Success:	non-negative
 *
 *		Failure:	negative
 *
 * Programmer:	Robb Matzke
 *		Friday, November 13, 1998
 *
 * Modifications:
 *
 *-------------------------------------------------------------------------
 */
herr_t
H5T_conv_uint_ushort(hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata,
		     size_t nelmts, size_t stride, void *buf, void UNUSED *bkg, hid_t UNUSED dset_xfer_plist)
{
    FUNC_ENTER(H5T_conv_uint_ushort, FAIL);
    H5T_CONV_Uu(UINT, USHORT,
		unsigned, unsigned short,
		USHRT_MAX);
    FUNC_LEAVE(SUCCEED);
}


/*-------------------------------------------------------------------------
 * Function:	H5T_conv_int_uint
 *
 * Purpose:	Converts `int' to `unsigned int'
 *
 * Return:	Success:	non-negative
 *
 *		Failure:	negative
 *
 * Programmer:	Robb Matzke
 *		Monday, November 16, 1998
 *
 * Modifications:
 *
 *-------------------------------------------------------------------------
 */
herr_t
H5T_conv_int_uint(hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata,
		  size_t nelmts, size_t stride, void *buf, void UNUSED *bkg, hid_t UNUSED dset_xfer_plist)
{
    FUNC_ENTER(H5T_conv_int_uint, FAIL);
    H5T_CONV_su(INT, UINT,
		int, unsigned);
    FUNC_LEAVE(SUCCEED);
}


/*-------------------------------------------------------------------------
 * Function:	H5T_conv_uint_int
 *
 * Purpose:	Converts `unsigned int' to `int'
 *
 * Return:	Success:	non-negative
 *
 *		Failure:	negative
 *
 * Programmer:	Robb Matzke
 *		Monday, November 16, 1998
 *
 * Modifications:
 *
 *-------------------------------------------------------------------------
 */
herr_t
H5T_conv_uint_int(hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata,
		  size_t nelmts, size_t stride, void *buf, void UNUSED *bkg, hid_t UNUSED dset_xfer_plist)
{
    FUNC_ENTER(H5T_conv_uint_int, FAIL);
    H5T_CONV_us(UINT, INT,
		unsigned, int,
		INT_MAX);
    FUNC_LEAVE(SUCCEED);
}


/*-------------------------------------------------------------------------
 * Function:	H5T_conv_int_long
 *
 * Purpose:	Converts `int' to `long'
 *
 * Return:	Success:	non-negative
 *
 *		Failure:	negative
 *
 * Programmer:	Robb Matzke
 *		Friday, November 13, 1998
 *
 * Modifications:
 *
 *-------------------------------------------------------------------------
 */
herr_t
H5T_conv_int_long(hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata,
		  size_t nelmts, size_t stride, void *buf, void UNUSED *bkg, hid_t UNUSED dset_xfer_plist)
{
    FUNC_ENTER(H5T_conv_int_long, FAIL);
    H5T_CONV_sS(INT, LONG,
		int, long);
    FUNC_LEAVE(SUCCEED);
}


/*-------------------------------------------------------------------------
 * Function:	H5T_conv_int_ulong
 *
 * Purpose:	Converts `int' to `unsigned long'
 *
 * Return:	Success:	Non-negative
 *
 *		Failure:	Negative
 *
 * Programmer:	Robb Matzke
 *		Friday, November 13, 1998
 *
 * Modifications:
 *
 *-------------------------------------------------------------------------
 */
herr_t
H5T_conv_int_ulong(hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata,
		   size_t nelmts, size_t stride, void *buf, void UNUSED *bkg, hid_t UNUSED dset_xfer_plist)
{
    FUNC_ENTER(H5T_conv_int_ulong, FAIL);
    H5T_CONV_sU(INT, LONG,
		int, unsigned long);
    FUNC_LEAVE(SUCCEED);
}


/*-------------------------------------------------------------------------
 * Function:	H5T_conv_uint_long
 *
 * Purpose:	Converts `unsigned int' to `long'
 *
 * Return:	Success:	Non-negative
 *
 *		Failure:	Negative
 *
 * Programmer:	Robb Matzke
 *		Friday, November 13, 1998
 *
 * Modifications:
 *
 *-------------------------------------------------------------------------
 */
herr_t
H5T_conv_uint_long(hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata,
		   size_t nelmts, size_t stride, void *buf, void UNUSED *bkg, hid_t UNUSED dset_xfer_plist)
{
    FUNC_ENTER(H5T_conv_uint_long, FAIL);
    H5T_CONV_uS(UINT, LONG,
		unsigned, long,
		LONG_MAX);
    FUNC_LEAVE(SUCCEED);
}


/*-------------------------------------------------------------------------
 * Function:	H5T_conv_uint_ulong
 *
 * Purpose:	Converts `unsigned int' to `unsigned long'
 *
 * Return:	Success:	non-negative
 *
 *		Failure:	negative
 *
 * Programmer:	Robb Matzke
 *		Friday, November 13, 1998
 *
 * Modifications:
 *
 *-------------------------------------------------------------------------
 */
herr_t
H5T_conv_uint_ulong(hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata,
		    size_t nelmts, size_t stride, void *buf, void UNUSED *bkg, hid_t UNUSED dset_xfer_plist)
{
    FUNC_ENTER(H5T_conv_uint_ulong, FAIL);
    H5T_CONV_uU(UINT, ULONG,
		unsigned, unsigned long);
    FUNC_LEAVE(SUCCEED);
}


/*-------------------------------------------------------------------------
 * Function:	H5T_conv_int_llong
 *
 * Purpose:	Converts `int' to `long_long'
 *
 * Return:	Success:	Non-negative
 *
 *		Failure:	Negative
 *
 * Programmer:	Robb Matzke
 *		Friday, November 13, 1998
 *
 * Modifications:
 *
 *-------------------------------------------------------------------------
 */
herr_t
H5T_conv_int_llong(hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata,
		   size_t nelmts, size_t stride, void *buf, void UNUSED *bkg, hid_t UNUSED dset_xfer_plist)
{
    FUNC_ENTER(H5T_conv_int_llong, FAIL);
    H5T_CONV_sS(INT, LLONG,
		int, long_long);
    FUNC_LEAVE(SUCCEED);
}


/*-------------------------------------------------------------------------
 * Function:	H5T_conv_int_ullong
 *
 * Purpose:	Converts `int' to `unsigned long_long'
 *
 * Return:	Success:	Non-negative
 *
 *		Failure:	Negative
 *
 * Programmer:	Robb Matzke
 *		Friday, November 13, 1998
 *
 * Modifications:
 *
 *-------------------------------------------------------------------------
 */
herr_t
H5T_conv_int_ullong(hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata,
		    size_t nelmts, size_t stride, void *buf, void UNUSED *bkg, hid_t UNUSED dset_xfer_plist)
{
    FUNC_ENTER(H5T_conv_int_ullong, FAIL);
    H5T_CONV_sU(INT, ULLONG,
		int, unsigned long_long);
    FUNC_LEAVE(SUCCEED);
}


/*-------------------------------------------------------------------------
 * Function:	H5T_conv_uint_llong
 *
 * Purpose:	Converts `unsigned int' to `long_long'
 *
 * Return:	Success:	Non-negative
 *
 *		Failure:	Negative
 *
 * Programmer:	Robb Matzke
 *		Friday, November 13, 1998
 *
 * Modifications:
 *
 *-------------------------------------------------------------------------
 */
herr_t
H5T_conv_uint_llong(hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata,
		    size_t nelmts, size_t stride, void *buf, void UNUSED *bkg, hid_t UNUSED dset_xfer_plist)
{
    FUNC_ENTER(H5T_conv_uint_llong, FAIL);
    H5T_CONV_uS(UINT, LLONG,
		unsigned, long_long,
		LLONG_MAX);
    FUNC_LEAVE(SUCCEED);
}


/*-------------------------------------------------------------------------
 * Function:	H5T_conv_uint_ullong
 *
 * Purpose:	Converts `unsigned int' to `unsigned long_long'
 *
 * Return:	Success:	Non-negative
 *
 *		Failure:	Negative
 *
 * Programmer:	Robb Matzke
 *		Friday, November 13, 1998
 *
 * Modifications:
 *
 *-------------------------------------------------------------------------
 */
herr_t
H5T_conv_uint_ullong(hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata,
		     size_t nelmts, size_t stride, void *buf, void UNUSED *bkg, hid_t UNUSED dset_xfer_plist)
{
    FUNC_ENTER(H5T_conv_uint_ullong, FAIL);
    H5T_CONV_uU(UINT, ULLONG,
		unsigned, unsigned long_long);
    FUNC_LEAVE(SUCCEED);
}


/*-------------------------------------------------------------------------
 * Function:	H5T_conv_long_schar
 *
 * Purpose:	Converts `long' to `signed char'
 *
 * Return:	Success:	non-negative
 *
 *		Failure:	negative
 *
 * Programmer:	Robb Matzke
 *		Friday, November 13, 1998
 *
 * Modifications:
 *
 *-------------------------------------------------------------------------
 */
herr_t
H5T_conv_long_schar(hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata,
		    size_t nelmts, size_t stride, void *buf, void UNUSED *bkg, hid_t UNUSED dset_xfer_plist)
{
    FUNC_ENTER(H5T_conv_long_schar, FAIL);
    H5T_CONV_Ss(LONG, SCHAR,
		long, signed char,
		SCHAR_MIN, SCHAR_MAX);
    FUNC_LEAVE(SUCCEED);
}


/*-------------------------------------------------------------------------
 * Function:	H5T_conv_long_uchar
 *
 * Purpose:	Converts `long' to `unsigned char'
 *
 * Return:	Success:	non-negative
 *
 *		Failure:	negative
 *
 * Programmer:	Robb Matzke
 *		Friday, November 13, 1998
 *
 * Modifications:
 *
 *-------------------------------------------------------------------------
 */
herr_t
H5T_conv_long_uchar(hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata,
		    size_t nelmts, size_t stride, void *buf, void UNUSED *bkg, hid_t UNUSED dset_xfer_plist)
{
    FUNC_ENTER(H5T_conv_long_uchar, FAIL);
    H5T_CONV_Su(LONG, UCHAR,
		long, unsigned char,
		UCHAR_MAX);
    FUNC_LEAVE(SUCCEED);
}


/*-------------------------------------------------------------------------
 * Function:	H5T_conv_ulong_schar
 *
 * Purpose:	Converts `unsigned long' to `signed char'
 *
 * Return:	Success:	non-negative
 *
 *		Failure:	negative
 *
 * Programmer:	Robb Matzke
 *		Friday, November 13, 1998
 *
 * Modifications:
 *
 *-------------------------------------------------------------------------
 */
herr_t
H5T_conv_ulong_schar(hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata,
		     size_t nelmts, size_t stride, void *buf, void UNUSED *bkg, hid_t UNUSED dset_xfer_plist)
{
    FUNC_ENTER(H5T_conv_ulong_schar, FAIL);
    H5T_CONV_Us(ULONG, SCHAR,
		unsigned long, signed char,
		SCHAR_MAX);
    FUNC_LEAVE(SUCCEED);
}


/*-------------------------------------------------------------------------
 * Function:	H5T_conv_ulong_uchar
 *
 * Purpose:	Converts `unsigned long' to `unsigned char'
 *
 * Return:	Success:	non-negative
 *
 *		Failure:	negative
 *
 * Programmer:	Robb Matzke
 *		Friday, November 13, 1998
 *
 * Modifications:
 *
 *-------------------------------------------------------------------------
 */
herr_t
H5T_conv_ulong_uchar(hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata,
		     size_t nelmts, size_t stride, void *buf, void UNUSED *bkg, hid_t UNUSED dset_xfer_plist)
{
    FUNC_ENTER(H5T_conv_ulong_uchar, FAIL);
    H5T_CONV_Uu(ULONG, UCHAR,
		unsigned long, unsigned char,
		UCHAR_MAX);
    FUNC_LEAVE(SUCCEED);
}


/*-------------------------------------------------------------------------
 * Function:	H5T_conv_long_short
 *
 * Purpose:	Converts `long' to `short'
 *
 * Return:	Success:	non-negative
 *
 *		Failure:	negative
 *
 * Programmer:	Robb Matzke
 *		Friday, November 13, 1998
 *
 * Modifications:
 *
 *-------------------------------------------------------------------------
 */
herr_t
H5T_conv_long_short(hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata,
		    size_t nelmts, size_t stride, void *buf, void UNUSED *bkg, hid_t UNUSED dset_xfer_plist)
{
    FUNC_ENTER(H5T_conv_long_short, FAIL);
    H5T_CONV_Ss(LONG, SHORT,
		long, short,
		SHRT_MIN, SHRT_MAX);
    FUNC_LEAVE(SUCCEED);
}


/*-------------------------------------------------------------------------
 * Function:	H5T_conv_long_ushort
 *
 * Purpose:	Converts `long' to `unsigned short'
 *
 * Return:	Success:	non-negative
 *
 *		Failure:	negative
 *
 * Programmer:	Robb Matzke
 *		Friday, November 13, 1998
 *
 * Modifications:
 *
 *-------------------------------------------------------------------------
 */
herr_t
H5T_conv_long_ushort(hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata,
		     size_t nelmts, size_t stride, void *buf, void UNUSED *bkg, hid_t UNUSED dset_xfer_plist)
{
    FUNC_ENTER(H5T_conv_long_ushort, FAIL);
    H5T_CONV_Su(LONG, USHORT,
		long, unsigned short,
		USHRT_MAX);
    FUNC_LEAVE(SUCCEED);
}


/*-------------------------------------------------------------------------
 * Function:	H5T_conv_ulong_short
 *
 * Purpose:	Converts `unsigned long' to `short'
 *
 * Return:	Success:	non-negative
 *
 *		Failure:	negative
 *
 * Programmer:	Robb Matzke
 *		Friday, November 13, 1998
 *
 * Modifications:
 *
 *-------------------------------------------------------------------------
 */
herr_t
H5T_conv_ulong_short(hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata,
		    size_t nelmts, size_t stride, void *buf, void UNUSED *bkg, hid_t UNUSED dset_xfer_plist)
{
    FUNC_ENTER(H5T_conv_ulong_short, FAIL);
    H5T_CONV_Us(ULONG, SHORT,
		unsigned long, short,
		SHRT_MAX);
    FUNC_LEAVE(SUCCEED);
}


/*-------------------------------------------------------------------------
 * Function:	H5T_conv_ulong_ushort
 *
 * Purpose:	Converts `unsigned long' to `unsigned short'
 *
 * Return:	Success:	non-negative
 *
 *		Failure:	negative
 *
 * Programmer:	Robb Matzke
 *		Friday, November 13, 1998
 *
 * Modifications:
 *
 *-------------------------------------------------------------------------
 */
herr_t
H5T_conv_ulong_ushort(hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata,
		      size_t nelmts, size_t stride, void *buf,
		      void UNUSED *bkg, hid_t UNUSED dset_xfer_plist)
{
    FUNC_ENTER(H5T_conv_ulong_ushort, FAIL);
    H5T_CONV_Uu(ULONG, USHORT,
		unsigned long, unsigned short,
		USHRT_MAX);
    FUNC_LEAVE(SUCCEED);
}


/*-------------------------------------------------------------------------
 * Function:	H5T_conv_long_int
 *
 * Purpose:	Converts `long' to `int'
 *
 * Return:	Success:	non-negative
 *
 *		Failure:	negative
 *
 * Programmer:	Robb Matzke
 *		Friday, November 13, 1998
 *
 * Modifications:
 *
 *-------------------------------------------------------------------------
 */
herr_t
H5T_conv_long_int(hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata,
		  size_t nelmts, size_t stride, void *buf, void UNUSED *bkg, hid_t UNUSED dset_xfer_plist)
{
    FUNC_ENTER(H5T_conv_long_int, FAIL);
    H5T_CONV_Ss(LONG, INT,
		long, int,
		INT_MIN, INT_MAX);
    FUNC_LEAVE(SUCCEED);
}


/*-------------------------------------------------------------------------
 * Function:	H5T_conv_long_uint
 *
 * Purpose:	Converts `long' to `unsigned int'
 *
 * Return:	Success:	non-negative
 *
 *		Failure:	negative
 *
 * Programmer:	Robb Matzke
 *		Friday, November 13, 1998
 *
 * Modifications:
 *
 *-------------------------------------------------------------------------
 */
herr_t
H5T_conv_long_uint(hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata,
		   size_t nelmts, size_t stride, void *buf, void UNUSED *bkg, hid_t UNUSED dset_xfer_plist)
{
    FUNC_ENTER(H5T_conv_long_uint, FAIL);
    H5T_CONV_Su(LONG, UINT,
		long, unsigned,
		UINT_MAX);
    FUNC_LEAVE(SUCCEED);
}


/*-------------------------------------------------------------------------
 * Function:	H5T_conv_ulong_int
 *
 * Purpose:	Converts `unsigned long' to `int'
 *
 * Return:	Success:	non-negative
 *
 *		Failure:	negative
 *
 * Programmer:	Robb Matzke
 *		Friday, November 13, 1998
 *
 * Modifications:
 *
 *-------------------------------------------------------------------------
 */
herr_t
H5T_conv_ulong_int(hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata,
		   size_t nelmts, size_t stride, void *buf, void UNUSED *bkg, hid_t UNUSED dset_xfer_plist)
{
    FUNC_ENTER(H5T_conv_ulong_int, FAIL);
    H5T_CONV_Us(ULONG, INT,
		unsigned long, int,
		INT_MAX);
    FUNC_LEAVE(SUCCEED);
}


/*-------------------------------------------------------------------------
 * Function:	H5T_conv_ulong_uint
 *
 * Purpose:	Converts `unsigned long' to `unsigned int'
 *
 * Return:	Success:	non-negative
 *
 *		Failure:	negative
 *
 * Programmer:	Robb Matzke
 *		Friday, November 13, 1998
 *
 * Modifications:
 *
 *-------------------------------------------------------------------------
 */
herr_t
H5T_conv_ulong_uint(hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata,
		    size_t nelmts, size_t stride, void *buf, void UNUSED *bkg, hid_t UNUSED dset_xfer_plist)
{
    FUNC_ENTER(H5T_conv_ulong_uint, FAIL);
    H5T_CONV_Uu(ULONG, UINT,
		unsigned long, unsigned,
		UINT_MAX);
    FUNC_LEAVE(SUCCEED);
}


/*-------------------------------------------------------------------------
 * Function:	H5T_conv_long_ulong
 *
 * Purpose:	Converts `long' to `unsigned long'
 *
 * Return:	Success:	non-negative
 *
 *		Failure:	negative
 *
 * Programmer:	Robb Matzke
 *		Monday, November 16, 1998
 *
 * Modifications:
 *
 *-------------------------------------------------------------------------
 */
herr_t
H5T_conv_long_ulong(hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata,
		    size_t nelmts, size_t stride, void *buf, void UNUSED *bkg, hid_t UNUSED dset_xfer_plist)
{
    FUNC_ENTER(H5T_conv_long_ulong, FAIL);
    H5T_CONV_su(LONG, ULONG,
		long, unsigned long);
    FUNC_LEAVE(SUCCEED);
}


/*-------------------------------------------------------------------------
 * Function:	H5T_conv_ulong_long
 *
 * Purpose:	Converts `unsigned long' to `long'
 *
 * Return:	Success:	non-negative
 *
 *		Failure:	negative
 *
 * Programmer:	Robb Matzke
 *		Monday, November 16, 1998
 *
 * Modifications:
 *
 *-------------------------------------------------------------------------
 */
herr_t
H5T_conv_ulong_long(hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata,
		    size_t nelmts, size_t stride, void *buf, void UNUSED *bkg, hid_t UNUSED dset_xfer_plist)
{
    FUNC_ENTER(H5T_conv_ulong_long, FAIL);
    H5T_CONV_us(ULONG, LONG,
		unsigned long, long,
		LONG_MAX);
    FUNC_LEAVE(SUCCEED);
}


/*-------------------------------------------------------------------------
 * Function:	H5T_conv_long_llong
 *
 * Purpose:	Converts `long' to `long_long'
 *
 * Return:	Success:	Non-negative
 *
 *		Failure:	Negative
 *
 * Programmer:	Robb Matzke
 *		Friday, November 13, 1998
 *
 * Modifications:
 *
 *-------------------------------------------------------------------------
 */
herr_t
H5T_conv_long_llong(hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata,
		    size_t nelmts, size_t stride, void *buf, void UNUSED *bkg, hid_t UNUSED dset_xfer_plist)
{
    FUNC_ENTER(H5T_conv_long_llong, FAIL);
    H5T_CONV_sS(LONG, LLONG,
		long, long_long);
    FUNC_LEAVE(SUCCEED);
}


/*-------------------------------------------------------------------------
 * Function:	H5T_conv_long_ullong
 *
 * Purpose:	Converts `long' to `unsigned long_long'
 *
 * Return:	Success:	Non-negative
 *
 *		Failure:	Negative
 *
 * Programmer:	Robb Matzke
 *		Friday, November 13, 1998
 *
 * Modifications:
 *
 *-------------------------------------------------------------------------
 */
herr_t
H5T_conv_long_ullong(hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata,
		     size_t nelmts, size_t stride, void *buf, void UNUSED *bkg, hid_t UNUSED dset_xfer_plist)
{
    FUNC_ENTER(H5T_conv_long_ullong, FAIL);
    H5T_CONV_sU(LONG, ULLONG,
		long, unsigned long_long);
    FUNC_LEAVE(SUCCEED);
}


/*-------------------------------------------------------------------------
 * Function:	H5T_conv_ulong_llong
 *
 * Purpose:	Converts `unsigned long' to `long_long'
 *
 * Return:	Success:	Non-negative
 *
 *		Failure:	Negative
 *
 * Programmer:	Robb Matzke
 *		Friday, November 13, 1998
 *
 * Modifications:
 *
 *-------------------------------------------------------------------------
 */
herr_t
H5T_conv_ulong_llong(hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata,
		     size_t nelmts, size_t stride, void *buf, void UNUSED *bkg, hid_t UNUSED dset_xfer_plist)
{
    FUNC_ENTER(H5T_conv_long_llong, FAIL);
    H5T_CONV_uS(ULONG, LLONG,
		unsigned long, long_long,
		LLONG_MAX);
    FUNC_LEAVE(SUCCEED);
}


/*-------------------------------------------------------------------------
 * Function:	H5T_conv_ulong_ullong
 *
 * Purpose:	Converts `unsigned long' to `unsigned long_long'
 *
 * Return:	Success:	Non-negative
 *
 *		Failure:	Negative
 *
 * Programmer:	Robb Matzke
 *		Friday, November 13, 1998
 *
 * Modifications:
 *
 *-------------------------------------------------------------------------
 */
herr_t
H5T_conv_ulong_ullong(hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata,
		      size_t nelmts, size_t stride, void *buf,
		      void UNUSED *bkg, hid_t UNUSED dset_xfer_plist)
{
    FUNC_ENTER(H5T_conv_ulong_ullong, FAIL);
    H5T_CONV_uU(ULONG, ULLONG,
		unsigned long, unsigned long_long);
    FUNC_LEAVE(SUCCEED);
}


/*-------------------------------------------------------------------------
 * Function:	H5T_conv_llong_schar
 *
 * Purpose:	Converts `long_long' to `signed char'
 *
 * Return:	Success:	Non-negative
 *
 *		Failure:	Negative
 *
 * Programmer:	Robb Matzke
 *		Friday, November 13, 1998
 *
 * Modifications:
 *
 *-------------------------------------------------------------------------
 */
herr_t
H5T_conv_llong_schar(hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata,
		     size_t nelmts, size_t stride, void *buf, void UNUSED *bkg, hid_t UNUSED dset_xfer_plist)
{
    FUNC_ENTER(H5T_conv_llong_schar, FAIL);
    H5T_CONV_Ss(LLONG, SCHAR,
		long_long, signed char,
		SCHAR_MIN, SCHAR_MAX);
    FUNC_LEAVE(SUCCEED);
}


/*-------------------------------------------------------------------------
 * Function:	H5T_conv_llong_uchar
 *
 * Purpose:	Converts `long_long' to `unsigned char'
 *
 * Return:	Success:	Non-negative
 *
 *		Failure:	Negative
 *
 * Programmer:	Robb Matzke
 *		Friday, November 13, 1998
 *
 * Modifications:
 *
 *-------------------------------------------------------------------------
 */
herr_t
H5T_conv_llong_uchar(hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata,
		     size_t nelmts, size_t stride, void *buf, void UNUSED *bkg, hid_t UNUSED dset_xfer_plist)
{
    FUNC_ENTER(H5T_conv_llong_uchar, FAIL);
    H5T_CONV_Su(LLONG, UCHAR,
		long_long, unsigned char,
		UCHAR_MAX);
    FUNC_LEAVE(SUCCEED);
}


/*-------------------------------------------------------------------------
 * Function:	H5T_conv_ullong_schar
 *
 * Purpose:	Converts `unsigned long_long' to `signed char'
 *
 * Return:	Success:	Non-negative
 *
 *		Failure:	Negative
 *
 * Programmer:	Robb Matzke
 *		Friday, November 13, 1998
 *
 * Modifications:
 *
 *-------------------------------------------------------------------------
 */
herr_t
H5T_conv_ullong_schar(hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata,
		      size_t nelmts, size_t stride, void *buf,
		      void UNUSED *bkg, hid_t UNUSED dset_xfer_plist)
{
    FUNC_ENTER(H5T_conv_ullong_schar, FAIL);
    H5T_CONV_Us(ULLONG, SCHAR,
		unsigned long_long, signed char,
		SCHAR_MAX);
    FUNC_LEAVE(SUCCEED);
}


/*-------------------------------------------------------------------------
 * Function:	H5T_conv_ullong_uchar
 *
 * Purpose:	Converts `unsigned long_long' to `unsigned char'
 *
 * Return:	Success:	Non-negative
 *
 *		Failure:	Negative
 *
 * Programmer:	Robb Matzke
 *		Friday, November 13, 1998
 *
 * Modifications:
 *
 *-------------------------------------------------------------------------
 */
herr_t
H5T_conv_ullong_uchar(hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata,
		    size_t nelmts, size_t stride, void *buf, void UNUSED *bkg, hid_t UNUSED dset_xfer_plist)
{
    FUNC_ENTER(H5T_conv_ullong_uchar, FAIL);
    H5T_CONV_Uu(ULLONG, UCHAR,
		unsigned long_long, unsigned char,
		UCHAR_MAX);
    FUNC_LEAVE(SUCCEED);
}


/*-------------------------------------------------------------------------
 * Function:	H5T_conv_llong_short
 *
 * Purpose:	Converts `long_long' to `short'
 *
 * Return:	Success:	Non-negative
 *
 *		Failure:	Negative
 *
 * Programmer:	Robb Matzke
 *		Friday, November 13, 1998
 *
 * Modifications:
 *
 *-------------------------------------------------------------------------
 */
herr_t
H5T_conv_llong_short(hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata,
		     size_t nelmts, size_t stride, void *buf, void UNUSED *bkg, hid_t UNUSED dset_xfer_plist)
{
    FUNC_ENTER(H5T_conv_llong_short, FAIL);
    H5T_CONV_Ss(LLONG, SHORT,
		long_long, short,
		SHRT_MIN, SHRT_MAX);
    FUNC_LEAVE(SUCCEED);
}


/*-------------------------------------------------------------------------
 * Function:	H5T_conv_llong_ushort
 *
 * Purpose:	Converts `long_long' to `unsigned short'
 *
 * Return:	Success:	Non-negative
 *
 *		Failure:	Negative
 *
 * Programmer:	Robb Matzke
 *		Friday, November 13, 1998
 *
 * Modifications:
 *
 *-------------------------------------------------------------------------
 */
herr_t
H5T_conv_llong_ushort(hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata,
		      size_t nelmts, size_t stride, void *buf,
		      void UNUSED *bkg, hid_t UNUSED dset_xfer_plist)
{
    FUNC_ENTER(H5T_conv_llong_ushort, FAIL);
    H5T_CONV_Su(LLONG, USHORT,
		long_long, unsigned short,
		USHRT_MAX);
    FUNC_LEAVE(SUCCEED);
}


/*-------------------------------------------------------------------------
 * Function:	H5T_conv_ullong_short
 *
 * Purpose:	Converts `unsigned long_long' to `short'
 *
 * Return:	Success:	Non-negative
 *
 *		Failure:	Negative
 *
 * Programmer:	Robb Matzke
 *		Friday, November 13, 1998
 *
 * Modifications:
 *
 *-------------------------------------------------------------------------
 */
herr_t
H5T_conv_ullong_short(hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata,
		      size_t nelmts, size_t stride, void *buf,
		      void UNUSED *bkg, hid_t UNUSED dset_xfer_plist)
{
    FUNC_ENTER(H5T_conv_ullong_short, FAIL);
    H5T_CONV_Us(ULLONG, SHORT,
		unsigned long_long, short,
		SHRT_MAX);
    FUNC_LEAVE(SUCCEED);
}


/*-------------------------------------------------------------------------
 * Function:	H5T_conv_ullong_ushort
 *
 * Purpose:	Converts `unsigned long_long' to `unsigned short'
 *
 * Return:	Success:	Non-negative
 *
 *		Failure:	Negative
 *
 * Programmer:	Robb Matzke
 *		Friday, November 13, 1998
 *
 * Modifications:
 *
 *-------------------------------------------------------------------------
 */
herr_t
H5T_conv_ullong_ushort(hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata,
		       size_t nelmts, size_t stride, void *buf,
		       void UNUSED *bkg, hid_t UNUSED dset_xfer_plist)
{
    FUNC_ENTER(H5T_conv_ullong_ushort, FAIL);
    H5T_CONV_Uu(ULLONG, USHORT,
		unsigned long_long, unsigned short,
		USHRT_MAX);
    FUNC_LEAVE(SUCCEED);
}


/*-------------------------------------------------------------------------
 * Function:	H5T_conv_llong_int
 *
 * Purpose:	Converts `long_long' to `int'
 *
 * Return:	Success:	Non-negative
 *
 *		Failure:	Negative
 *
 * Programmer:	Robb Matzke
 *		Friday, November 13, 1998
 *
 * Modifications:
 *
 *-------------------------------------------------------------------------
 */
herr_t
H5T_conv_llong_int(hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata,
		   size_t nelmts, size_t stride, void *buf, void UNUSED *bkg, hid_t UNUSED dset_xfer_plist)
{
    FUNC_ENTER(H5T_conv_llong_int, FAIL);
    H5T_CONV_Ss(LLONG, INT,
		long_long, int,
		INT_MIN, INT_MAX);
    FUNC_LEAVE(SUCCEED);
}


/*-------------------------------------------------------------------------
 * Function:	H5T_conv_llong_uint
 *
 * Purpose:	Converts `long_long' to `unsigned int'
 *
 * Return:	Success:	Non-negative
 *
 *		Failure:	Negative
 *
 * Programmer:	Robb Matzke
 *		Friday, November 13, 1998
 *
 * Modifications:
 *
 *-------------------------------------------------------------------------
 */
herr_t
H5T_conv_llong_uint(hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata,
		    size_t nelmts, size_t stride, void *buf, void UNUSED *bkg, hid_t UNUSED dset_xfer_plist)
{
    FUNC_ENTER(H5T_conv_llong_uint, FAIL);
    H5T_CONV_Su(LLONG, UINT,
		long_long, unsigned,
		UINT_MAX);
    FUNC_LEAVE(SUCCEED);
}


/*-------------------------------------------------------------------------
 * Function:	H5T_conv_ullong_int
 *
 * Purpose:	Converts `unsigned long_long' to `int'
 *
 * Return:	Success:	Non-negative
 *
 *		Failure:	Negative
 *
 * Programmer:	Robb Matzke
 *		Friday, November 13, 1998
 *
 * Modifications:
 *
 *-------------------------------------------------------------------------
 */
herr_t
H5T_conv_ullong_int(hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata,
		    size_t nelmts, size_t stride, void *buf, void UNUSED *bkg, hid_t UNUSED dset_xfer_plist)
{
    FUNC_ENTER(H5T_conv_ullong_int, FAIL);
    H5T_CONV_Us(ULLONG, INT,
		unsigned long_long, int,
		INT_MAX);
    FUNC_LEAVE(SUCCEED);
}


/*-------------------------------------------------------------------------
 * Function:	H5T_conv_ullong_uint
 *
 * Purpose:	Converts `unsigned long_long' to `unsigned int'
 *
 * Return:	Success:	Non-negative
 *
 *		Failure:	Negative
 *
 * Programmer:	Robb Matzke
 *		Friday, November 13, 1998
 *
 * Modifications:
 *
 *-------------------------------------------------------------------------
 */
herr_t
H5T_conv_ullong_uint(hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata,
		     size_t nelmts, size_t stride, void *buf, void UNUSED *bkg, hid_t UNUSED dset_xfer_plist)
{
    FUNC_ENTER(H5T_conv_ullong_uint, FAIL);
    H5T_CONV_Uu(ULLONG, UINT,
		unsigned long_long, unsigned,
		UINT_MAX);
    FUNC_LEAVE(SUCCEED);
}


/*-------------------------------------------------------------------------
 * Function:	H5T_conv_llong_long
 *
 * Purpose:	Converts `long_long' to `long'
 *
 * Return:	Success:	Non-negative
 *
 *		Failure:	Negative
 *
 * Programmer:	Robb Matzke
 *		Friday, November 13, 1998
 *
 * Modifications:
 *
 *-------------------------------------------------------------------------
 */
herr_t
H5T_conv_llong_long(hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata,
		    size_t nelmts, size_t stride, void *buf, void UNUSED *bkg, hid_t UNUSED dset_xfer_plist)
{
    FUNC_ENTER(H5T_conv_llong_long, FAIL);
    H5T_CONV_Ss(LLONG, LONG,
		long_long, long,
		LONG_MIN, LONG_MAX);
    FUNC_LEAVE(SUCCEED);
}


/*-------------------------------------------------------------------------
 * Function:	H5T_conv_llong_ulong
 *
 * Purpose:	Converts `long_long' to `unsigned long'
 *
 * Return:	Success:	Non-negative
 *
 *		Failure:	Negative
 *
 * Programmer:	Robb Matzke
 *		Friday, November 13, 1998
 *
 * Modifications:
 *
 *-------------------------------------------------------------------------
 */
herr_t
H5T_conv_llong_ulong(hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata,
		     size_t nelmts, size_t stride, void *buf, void UNUSED *bkg, hid_t UNUSED dset_xfer_plist)
{
    FUNC_ENTER(H5T_conv_llong_ulong, FAIL);
    H5T_CONV_Su(LLONG, ULONG,
		long_long, unsigned long,
		ULONG_MAX);
    FUNC_LEAVE(SUCCEED);
}


/*-------------------------------------------------------------------------
 * Function:	H5T_conv_ullong_long
 *
 * Purpose:	Converts `unsigned long_long' to `long'
 *
 * Return:	Success:	Non-negative
 *
 *		Failure:	Negative
 *
 * Programmer:	Robb Matzke
 *		Friday, November 13, 1998
 *
 * Modifications:
 *
 *-------------------------------------------------------------------------
 */
herr_t
H5T_conv_ullong_long(hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata,
		     size_t nelmts, size_t stride, void *buf, void UNUSED *bkg, hid_t UNUSED dset_xfer_plist)
{
    FUNC_ENTER(H5T_conv_ullong_long, FAIL);
    H5T_CONV_Us(ULLONG, LONG,
		unsigned long_long, long,
		LONG_MAX);
    FUNC_LEAVE(SUCCEED);
}


/*-------------------------------------------------------------------------
 * Function:	H5T_conv_ullong_ulong
 *
 * Purpose:	Converts `unsigned long_long' to `unsigned long'
 *
 * Return:	Success:	Non-negative
 *
 *		Failure:	Negative
 *
 * Programmer:	Robb Matzke
 *		Friday, November 13, 1998
 *
 * Modifications:
 *
 *-------------------------------------------------------------------------
 */
herr_t
H5T_conv_ullong_ulong(hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata,
		      size_t nelmts, size_t stride, void *buf,
		      void UNUSED *bkg, hid_t UNUSED dset_xfer_plist)
{
    FUNC_ENTER(H5T_conv_ullong_ulong, FAIL);
    H5T_CONV_Uu(ULLONG, ULONG,
		unsigned long_long, unsigned long,
		ULONG_MAX);
    FUNC_LEAVE(SUCCEED);
}


/*-------------------------------------------------------------------------
 * Function:	H5T_conv_llong_ullong
 *
 * Purpose:	Converts `long_long' to `unsigned long_long'
 *
 * Return:	Success:	non-negative
 *
 *		Failure:	negative
 *
 * Programmer:	Robb Matzke
 *		Monday, November 16, 1998
 *
 * Modifications:
 *
 *-------------------------------------------------------------------------
 */
herr_t
H5T_conv_llong_ullong(hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata,
		      size_t nelmts, size_t stride, void *buf,
		      void UNUSED *bkg, hid_t UNUSED dset_xfer_plist)
{
    FUNC_ENTER(H5T_conv_llong_ullong, FAIL);
    H5T_CONV_su(LLONG, ULLONG,
		long_long, unsigned long_long);
    FUNC_LEAVE(SUCCEED);
}


/*-------------------------------------------------------------------------
 * Function:	H5T_conv_ullong_llong
 *
 * Purpose:	Converts `unsigned long_long' to `long_long'
 *
 * Return:	Success:	non-negative
 *
 *		Failure:	negative
 *
 * Programmer:	Robb Matzke
 *		Monday, November 16, 1998
 *
 * Modifications:
 *
 *-------------------------------------------------------------------------
 */
herr_t
H5T_conv_ullong_llong(hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata,
		      size_t nelmts, size_t stride, void *buf,
		      void UNUSED *bkg, hid_t UNUSED dset_xfer_plist)
{
    FUNC_ENTER(H5T_conv_ullong_llong, FAIL);
    H5T_CONV_us(ULLONG, LLONG,
		unsigned long_long, long_long,
		LLONG_MAX);
    FUNC_LEAVE(SUCCEED);
}


/*-------------------------------------------------------------------------
 * Function:	H5T_conv_float_double
 *
 * Purpose:	Convert native `float' to native `double' using hardware.
 *		This is a fast special case.
 *
 * Return:	Non-negative on success/Negative on failure
 *
 * Programmer:	Robb Matzke
 *		Tuesday, June 23, 1998
 *
 * Modifications:
 *		Robb Matzke, 1999-06-16
 *		Added support for non-zero strides. If STRIDE is non-zero
 *		then convert one value at each memory location advancing
 *		STRIDE bytes each time; otherwise assume both source and
 *		destination values are packed.
 *-------------------------------------------------------------------------
 */
herr_t
H5T_conv_float_double (hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata,
		       size_t nelmts, size_t stride, void *buf,
		       void UNUSED *bkg, hid_t UNUSED dset_xfer_plist)
{
    size_t	elmtno;			/*element number		*/
    uint8_t	*src, *s;		/*source buffer			*/
    uint8_t	*dst, *d;		/*destination buffer		*/
    H5T_t	*st, *dt;		/*type descriptors		*/
    hbool_t	src_mv, dst_mv;		/*align data?			*/
    double	aligned;		/*aligned data			*/
    H5T_conv_hw_t *priv = cdata->priv;	/*private data			*/
    
    FUNC_ENTER (H5T_conv_float_double, FAIL);

    switch (cdata->command) {
    case H5T_CONV_INIT:
	cdata->need_bkg = H5T_BKG_NO;
	if (NULL==(st=H5I_object(src_id)) ||
	    NULL==(dt=H5I_object(dst_id))) {
	    HRETURN_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL,
			  "unable to dereference data type object ID");
	}
	if (st->size!=sizeof(float) || dt->size!=sizeof(double)) {
	    HRETURN_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL,
			  "disagreement about data type size");
	}
	if (NULL==(cdata->priv=H5MM_calloc(sizeof(H5T_conv_hw_t)))) {
	    HRETURN_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL,
			  "memory allocation failed");
	}
	break;

    case H5T_CONV_FREE:
	CI_PRINT_STATS(FLOAT, DOUBLE);
	cdata->priv = H5MM_xfree(cdata->priv);
	break;

    case H5T_CONV_CONV:
	if (stride) {
	    src = dst = (uint8_t*)buf + stride*(nelmts-1);
	} else {
	    src = (uint8_t*)buf + sizeof(float)*(nelmts-1);
	    dst = (uint8_t*)buf + sizeof(double)*(nelmts-1);
	}
	
	/* Need alignment? */
	if (H5T_NATIVE_FLOAT_ALIGN_g>1) {
	    src_mv = ((size_t)buf % H5T_NATIVE_FLOAT_ALIGN_g) ||
		     ((stride?stride:sizeof(float)) %
		      H5T_NATIVE_FLOAT_ALIGN_g);
	} else {
	    src_mv = FALSE;
	}
	if (H5T_NATIVE_DOUBLE_ALIGN_g>1) {
	    dst_mv = ((size_t)buf % H5T_NATIVE_DOUBLE_ALIGN_g) ||
		     ((stride?stride:sizeof(double)) %
		      H5T_NATIVE_DOUBLE_ALIGN_g);
	} else {
	    dst_mv = FALSE;
	}
	if (src_mv) priv->s_aligned += nelmts;
	if (dst_mv) priv->d_aligned += nelmts;
	
	for (elmtno=0; elmtno<nelmts; elmtno++) {
	    /* Align source and/or destination */
	    if (src_mv) {
		HDmemcpy(&aligned, src, sizeof(float));
		s = (uint8_t*)&aligned;
	    } else {
		s = src;
	    }
	    if (dst_mv) d = (uint8_t*)&aligned;
	    else d = dst;

	    /* Conversion */
	    *((double*)d) = *((float*)s);

	    /* Unalign destination */
	    if (dst_mv) HDmemcpy(dst, &aligned, sizeof(double));

	    /* Advance buffer pointers */
	    if (stride) {
		src -= stride;
		dst -= stride;
	    } else {
		src -= sizeof(float);
		dst -= sizeof(double);
	    }
	}
	break;
	    
    default:
	HRETURN_ERROR (H5E_DATATYPE, H5E_UNSUPPORTED, FAIL,
		       "unknown conversion command");
    }

    FUNC_LEAVE (SUCCEED);
}


/*-------------------------------------------------------------------------
 * Function:	H5T_conv_double_float
 *
 * Purpose:	Convert native `double' to native `float' using hardware.
 *		This is a fast special case.
 *
 * Return:	Non-negative on success/Negative on failure
 *
 * Programmer:	Robb Matzke
 *		Tuesday, June 23, 1998
 *
 * Modifications:
 *		Robb Matzke, 7 Jul 1998
 *		Added overflow handling.
 *
 *		Robb Matzke, 1999-06-16
 *		Added support for non-zero strides. If STRIDE is non-zero
 *		then convert one value at each memory location advancing
 *		STRIDE bytes each time; otherwise assume both source and
 *		destination values are packed.
 *-------------------------------------------------------------------------
 */
herr_t
H5T_conv_double_float (hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata,
		       size_t nelmts, size_t stride, void *buf,
                       void UNUSED *bkg, hid_t UNUSED dset_xfer_plist)
{
    size_t	elmtno;			/*element number		*/
    uint8_t	*src, *s;		/*source buffer			*/
    uint8_t	*dst, *d;		/*destination buffer		*/
    H5T_t	*st, *dt;		/*type descriptors		*/
    hbool_t	src_mv, dst_mv;		/*align data?			*/
    double	aligned;		/*aligned data			*/
    H5T_conv_hw_t *priv = cdata->priv;	/*private data			*/
    
    FUNC_ENTER (H5T_conv_double_float, FAIL);

    switch (cdata->command) {
    case H5T_CONV_INIT:
	cdata->need_bkg = H5T_BKG_NO;
	if (NULL==(st=H5I_object(src_id)) ||
	    NULL==(dt=H5I_object(dst_id))) {
	    HRETURN_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL,
			  "unable to dereference data type object ID");
	}
	if (st->size!=sizeof(double) || dt->size!=sizeof(float)) {
	    HRETURN_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL,
			  "disagreement about data type size");
	}
	if (NULL==(cdata->priv=H5MM_calloc(sizeof(H5T_conv_hw_t)))) {
	    HRETURN_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL,
			  "memory allocation failed");
	}
	break;

    case H5T_CONV_FREE:
	CI_PRINT_STATS(DOUBLE, FLOAT);
	cdata->priv = H5MM_xfree(cdata->priv);
	break;

    case H5T_CONV_CONV:
	src = (uint8_t*)buf;
	dst = (uint8_t*)buf;

	/* Need alignment? */
	if (H5T_NATIVE_DOUBLE_ALIGN_g>1) {
	    src_mv = ((size_t)buf % H5T_NATIVE_DOUBLE_ALIGN_g) ||
		     ((stride?stride:sizeof(double)) %
		      H5T_NATIVE_DOUBLE_ALIGN_g);
	} else {
	    src_mv = FALSE;
	}
	if (H5T_NATIVE_FLOAT_ALIGN_g>1) {
	    dst_mv = ((size_t)buf % H5T_NATIVE_FLOAT_ALIGN_g) ||
		     ((stride?stride:sizeof(float)) %
		      H5T_NATIVE_FLOAT_ALIGN_g);
	} else {
	    dst_mv = FALSE;
	}
	if (src_mv) priv->s_aligned += nelmts;
	if (dst_mv) priv->d_aligned += nelmts;
	
	for (elmtno=0; elmtno<nelmts; elmtno++) {
	    /* Align source and/or destination */
	    if (src_mv) {
		HDmemcpy(&aligned, src, sizeof(double));
		s = (uint8_t*)&aligned;
	    } else {
		s = src;
	    }
	    if (dst_mv) d = (uint8_t*)&aligned;
	    else d = dst;

	    /* Conversion */
	    if (*((double*)s) > FLT_MAX) {
		if (!H5T_overflow_g ||
		    (H5T_overflow_g)(src_id, dst_id, s, d)<0) {
		    *((float*)d) = HUGE_VAL;
		}
	    } else if (*((double*)s) < -FLT_MAX) {
		if (!H5T_overflow_g ||
		    (H5T_overflow_g)(src_id, dst_id, s, d)<0) {
		    *((float*)d) = -HUGE_VAL;
		}
	    } else {
		*((float*)d) = *((double*)s);
	    }

	    /* Unalign destination */
	    if (dst_mv) HDmemcpy(dst, &aligned, sizeof(float));

            /* Advance pointers */
	    if (stride) {
		src += stride;
		dst += stride;
            } else {
		src += sizeof(double);
                dst += sizeof(float);
            }
	}
	break;
	    
    default:
	HRETURN_ERROR (H5E_DATATYPE, H5E_UNSUPPORTED, FAIL,
		       "unknown conversion command");
    }

    FUNC_LEAVE (SUCCEED);
}


/*-------------------------------------------------------------------------
 * Function:	H5T_conv_i32le_f64le
 *
 * Purpose:	Converts 4-byte little-endian integers (signed or unsigned)
 *		to 8-byte litte-endian IEEE floating point.
 *
 * Return:	Non-negative on success/Negative on failure
 *
 *
 * Programmer:	Robb Matzke
 *		Wednesday, June 10, 1998
 *
 * Modifications:
 *		Robb Matzke, 1999-06-16
 *		Added support for non-zero strides. If STRIDE is non-zero
 *		then convert one value at each memory location advancing
 *		STRIDE bytes each time; otherwise assume both source and
 *		destination values are packed.
 *-------------------------------------------------------------------------
 */
herr_t
H5T_conv_i32le_f64le (hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata,
		      size_t nelmts, size_t stride, void *buf,
                      void UNUSED *bkg, hid_t UNUSED dset_xfer_plist)
{
    uint8_t	*s=NULL, *d=NULL;	/*src and dst buf pointers	*/
    uint8_t	tmp[8];			/*temporary destination buffer	*/
    H5T_t	*src = NULL;		/*source data type		*/
    size_t	elmtno;			/*element counter		*/
    uintn	sign;			/*sign bit			*/
    uintn	cin, cout;		/*carry in/out			*/
    uintn	mbits=0;		/*mantissa bits			*/
    uintn	exponent;		/*exponent			*/
    intn	i;			/*counter			*/

    FUNC_ENTER (H5T_conv_i32le_f64le, FAIL);

    switch (cdata->command) {
    case H5T_CONV_INIT:
	assert (sizeof(intn)>=4);
	cdata->need_bkg = H5T_BKG_NO;
	break;

    case H5T_CONV_FREE:
	/* Free private data */
	break;

    case H5T_CONV_CONV:
	/* The conversion */
	if (H5I_DATATYPE!=H5I_get_type (src_id) ||
	    NULL==(src=H5I_object (src_id)) ||
	    H5I_DATATYPE!=H5I_get_type (dst_id) ||
	    NULL==H5I_object (dst_id)) {
	    HRETURN_ERROR (H5E_ARGS, H5E_BADTYPE, FAIL, "not a data type");
	}
	
	s = (uint8_t*)buf + (stride?stride:4)*(nelmts-1);
	d = (uint8_t*)buf + (stride?stride:8)*(nelmts-1);
	for (elmtno=0; elmtno<nelmts; elmtno++) {

	    /*
	     * If this is the last element to convert (that is, the first
	     * element of the buffer) then the source and destination areas
	     * overlap so we need to use a temp buf for the destination.
	     */
	    if ((void*)s==buf) d = tmp;

	    /* Convert the integer to a sign and magnitude */
	    switch (src->u.atomic.u.i.sign) {
	    case H5T_SGN_NONE:
		sign = 0;
		break;
	    case H5T_SGN_2:
		if (s[3] & 0x80) {
		    sign = 1;
		    for (i=0,cin=1; i<4; i++,cin=cout) {
			s[i] = ~s[i];
			cout = ((unsigned)(s[i])+cin > 0xff) ? 1 : 0;
			s[i] += cin;
		    }
		} else {
		    sign = 0;
		}
		break;
	    default:
		HRETURN_ERROR (H5E_DATATYPE, H5E_UNSUPPORTED, FAIL,
			       "unsupported integer sign method");
	    }
	    
	    /*
	     * Where is the most significant bit that is set?  We could do
	     * this in a loop, but testing it this way might be faster.
	     */
	    if (s[3]) {
		if (s[3] & 0x80) mbits = 32;
		else if (s[3] & 0x40) mbits = 31;
		else if (s[3] & 0x20) mbits = 30;
		else if (s[3] & 0x10) mbits = 29;
		else if (s[3] & 0x08) mbits = 28;
		else if (s[3] & 0x04) mbits = 27;
		else if (s[3] & 0x02) mbits = 26;
		else if (s[3] & 0x01) mbits = 25;
	    } else if (s[2]) {
		if (s[2] & 0x80) mbits = 24;
		else if (s[2] & 0x40) mbits = 23;
		else if (s[2] & 0x20) mbits = 22;
		else if (s[2] & 0x10) mbits = 21;
		else if (s[2] & 0x08) mbits = 20;
		else if (s[2] & 0x04) mbits = 19;
		else if (s[2] & 0x02) mbits = 18;
		else if (s[2] & 0x01) mbits = 17;
	    } else if (s[1]) {
		if (s[1] & 0x80) mbits = 16;
		else if (s[1] & 0x40) mbits = 15;
		else if (s[1] & 0x20) mbits = 14;
		else if (s[1] & 0x10) mbits = 13;
		else if (s[1] & 0x08) mbits = 12;
		else if (s[1] & 0x04) mbits = 11;
		else if (s[1] & 0x02) mbits = 10;
		else if (s[1] & 0x01) mbits =  9;
	    } else if (s[0]) {
		if (s[0] & 0x80) mbits = 8;
		else if (s[0] & 0x40) mbits =  7;
		else if (s[0] & 0x20) mbits =  6;
		else if (s[0] & 0x10) mbits =  5;
		else if (s[0] & 0x08) mbits =  4;
		else if (s[0] & 0x04) mbits =  3;
		else if (s[0] & 0x02) mbits =  2;
		else if (s[0] & 0x01) mbits =  1;
	    } else {
		/*zero*/
		d[7] = d[6] = d[5] = d[4] = d[3] = d[2] = d[1] = d[0] = 0;
		continue;
	    }

	    /*
	     * The sign and exponent.
	     */
	    exponent = (mbits - 1) + 1023;
	    d[7] = (sign<<7) | ((exponent>>4) & 0x7f);
	    d[6] = (exponent & 0x0f) << 4;
      
	    /*
	     * The mantissa.
	     */
	    switch (mbits) {
	    case 32:
		d[5] = d[4] = d[3] = d[1] = d[0] = 0;
		break;
	    case 31:
		d[6] |=	 0x0f	 & (s[3]>>2);
		d[5] = (s[3]<<6) | (s[2]>>2);
		d[4] = (s[2]<<6) | (s[1]>>2);
		d[3] = (s[1]<<6) | (s[0]>>2);
		d[2] = (s[0]<<6);
		d[1] = d[0] = 0;
		break;
	    case 30:
		d[6] |=	 0x0f	 & (s[3]>>1);
		d[5] = (s[3]<<7) | (s[2]>>1);
		d[4] = (s[2]<<7) | (s[1]>>1);
		d[3] = (s[1]<<7) | (s[0]>>1);
		d[2] = (s[0]<<7);
		d[1] = d[0] = 0;
		break;
	    case 29:
		d[6] |=	 0x0f	 & s[3];
		d[5] = s[2];
		d[4] = s[1];
		d[3] = s[0];
		d[2] = d[1] = d[0] = 0;
		break;
	    case 28:
		d[6] |= ((s[3]<<1) | (s[2]>>7)) & 0x0f;
		d[5] =	 (s[2]<<1) | (s[1]>>7);
		d[4] =	 (s[1]<<1) | (s[0]>>7);
		d[3] =	 (s[0]<<1);
		d[2] = d[1] = d[0] = 0;
		break;
	    case 27:
		d[6] |= ((s[3]<<2) | (s[2]>>6)) & 0x0f;
		d[5] =	 (s[2]<<2) | (s[1]>>6);
		d[4] =	 (s[1]<<2) | (s[0]>>6);
		d[3] =	 (s[0]<<2);
		d[2] = d[1] = d[0] = 0;
		break;
	    case 26:
		d[6] |= ((s[3]<<3) | (s[2]>>5)) & 0x0f;
		d[5] =	 (s[2]<<3) | (s[1]>>5);
		d[4] =	 (s[1]<<3) | (s[0]>>5);
		d[3] =	 (s[0]<<3);
		d[2] = d[1] = d[0] = 0;
		break;
	    case 25:
		d[6] |=	  0x0f	 & (s[2]>>4);
		d[5] = (s[2]<<4) | (s[1]>>4);
		d[4] = (s[1]<<4) | (s[0]>>4);
		d[3] = (s[0]<<4);
		d[2] = d[1] = d[0] = 0;
		break;
	    case 24:
		d[6] |=	  0x0f	 & (s[2]>>3);
		d[5] = (s[2]<<5) | (s[1]>>3);
		d[4] = (s[1]<<5) | (s[0]>>3);
		d[3] = (s[0]<<5);
		d[2] = d[1] = d[0] = 0;
		break;
	    case 23:
		d[6] |=	  0x0f	 & (s[2]>>2);
		d[5] = (s[2]<<6) | (s[1]>>2);
		d[4] = (s[1]<<6) | (s[0]>>2);
		d[3] = (s[0]<<6);
		d[2] = d[1] = d[0] = 0;
		break;
	    case 22:
		d[6] |=	  0x0f	 & (s[2]>>1);
		d[5] = (s[2]<<7) | (s[1]>>1);
		d[4] = (s[1]<<7) | (s[0]>>1);
		d[3] = (s[0]<<7);
		d[2] = d[1] = d[0] = 0;
		break;
	    case 21:
		d[6] |= 0x0f & s[2];
		d[5] = s[1];
		d[4] = s[0];
		d[3] = d[2] = d[1] = d[0] = 0;
		break;
	    case 20:
		d[6] |= ((s[2]<<1) | (s[1]>>7)) & 0x0f;
		d[5] =	 (s[1]<<1) | (s[0]>>7);
		d[4] =	 (s[0]<<1);
		d[3] = d[2] = d[1] = d[0] = 0;
		break;
	    case 19:
		d[6] |= ((s[2]<<2) | (s[1]>>6)) & 0x0f;
		d[5] =	 (s[1]<<2) | (s[0]>>6);
		d[4] =	 (s[0]<<2);
		d[3] = d[2] = d[1] = d[0] = 0;
		break;
	    case 18:
		d[6] |= ((s[2]<<3) | (s[1]>>5)) & 0x0f;
		d[5] =	 (s[1]<<3) | (s[0]>>5);
		d[4] =	 (s[0]<<3);
		d[3] = d[2] = d[1] = d[0] = 0;
		break;
	    case 17:
		d[6] |=	  0x0f	 & (s[1]>>4);
		d[5] = (s[1]<<4) | (s[0]>>4);
		d[4] = (s[0]<<4);
		d[3] = d[2] = d[1] = d[0] = 0;
		break;
	    case 16:
		d[6] |=	  0x0f	 & (s[1]>>3);
		d[5] = (s[1]<<5) | (s[0]>>3);
		d[4] = (s[0]<<5);
		d[3] = d[2] = d[1] = d[0] = 0;
		break;
	    case 15:
		d[6] |=	  0x0f	 & (s[1]>>2);
		d[5] = (s[1]<<6) | (s[0]>>2);
		d[4] = (s[0]<<6);
		d[3] = d[2] = d[1] = d[0] = 0;
		break;
	    case 14:
		d[6] |=	  0x0f	 & (s[1]>>1);
		d[5] = (s[1]<<7) | (s[0]>>1);
		d[4] = (s[0]<<7);
		d[3] = d[2] = d[1] = d[0] = 0;
		break;
	    case 13:
		d[6] |= 0x0f & s[1];
		d[5] = s[0];
		d[4] = d[3] = d[2] = d[1] = d[0] = 0;
		break;
	    case 12:
		d[6] |= ((s[1]<<1) | (s[0]>>7)) & 0x0f;
		d[5] =	 (s[0]<<1);
		d[4] = d[3] = d[2] = d[1] = d[0] = 0;
		break;
	    case 11:
		d[6] |= ((s[1]<<2) | (s[0]>>6)) & 0x0f;
		d[5] =	 (s[0]<<2);
		d[4] = d[3] = d[2] = d[1] = d[0] = 0;
		break;
	    case 10:
		d[6] |= ((s[1]<<3) | (s[0]>>5)) & 0x0f;
		d[5] =	 (s[0]<<3);
		d[4] = d[3] = d[2] = d[1] = d[0] = 0;
		break;
	    case 9:
		d[6] |=	  0x0f	 & (s[0]>>4);
		d[5] = (s[0]<<4);
		d[4] = d[3] = d[2] = d[1] = d[0] = 0;
		break;
	    case 8:
		d[6] |=	  0x0f	 & (s[0]>>3);
		d[5] = (s[0]<<5);
		d[4] = d[3] = d[2] = d[1] = d[0] = 0;
		break;
	    case 7:
		d[6] |=	  0x0f	 & (s[0]>>2);
		d[5] = (s[0]<<6);
		d[4] = d[3] = d[2] = d[1] = d[0] = 0;
		break;
	    case 6:
		d[6] |=	  0x0f	 & (s[0]>>1);
		d[5] = (s[0]<<7);
		d[4] = d[3] = d[2] = d[1] = d[0] = 0;
		break;
	    case 5:
		d[6] |= 0x0f & s[0];
		d[5] = d[4] = d[3] = d[2] = d[1] = d[0] = 0;
		break;
	    case 4:
		d[6] |= (s[0]<<1) & 0x0f;
		d[5] = d[4] = d[3] = d[2] = d[1] = d[0] = 0;
		break;
	    case 3:
		d[6] |= (s[0]<<2) & 0x0f;
		d[5] = d[4] = d[3] = d[2] = d[1] = d[0] = 0;
		break;
	    case 2:
		d[6] |= (s[0]<<3) & 0x0f;
		d[5] = d[4] = d[3] = d[2] = d[1] = d[0] = 0;
		break;
	    case 1:
		d[5] = d[4] = d[3] = d[2] = d[1] = d[0] = 0;
		break;
	    }

	    /*
	     * Copy temp buffer to the destination.  This only happens for
	     * the first value in the array, the last value processed. See
	     * beginning of loop.
	     */
	    if (d==tmp) HDmemcpy (s, d, 8);

	    /* Advance pointers */
	    if (stride) {
		s -= stride;
		d -= stride;
	    } else {
		s -= 4;
		d -= 8;
	    }
	}
	break;

    default:
	/* Some other command we don't know about yet.*/
	HRETURN_ERROR (H5E_DATATYPE, H5E_UNSUPPORTED, FAIL,
		       "unknown conversion command");
    }
    
    FUNC_LEAVE (SUCCEED);
}