dnl
dnl sjl: this version of ncx.m4 has SX-specific optimisations as per
dnl      Harveys mods to earlier versions. However, I have removed
dnl      support for FLOAT2 and attempted to tidy up the mods to
dnl      reduce the complexity a bit
dnl
dnl This is m4 source.
dnl Process using m4 to produce 'C' language file.
dnl
dnl If you see this line, you can ignore the next one.
/* Do not edit this file. It is produced from the corresponding .m4 source */
dnl
/*
 *	Copyright 1996, University Corporation for Atmospheric Research
 *	See netcdf/COPYRIGHT file for copying and redistribution conditions.
 *
 * 	This file contains some routines derived from code
 *	which is copyrighted by Sun Microsystems, Inc.
 *	The "#ifdef vax" versions of
 *		 ncx_put_float_float()
 *		 ncx_get_float_float()
 *		 ncx_put_double_double()
 *		 ncx_get_double_double()
 *		 ncx_putn_float_float()
 *		 ncx_getn_float_float()
 *		 ncx_putn_double_double()
 *		 ncx_getn_double_double()
 * 	are derived from xdr_float() and xdr_double() routines
 *	in the freely available, copyrighted Sun RPCSRC 3.9
 *	distribution, xdr_float.c.
 * 	Our "value added" is that these are always memory to memory,
 *	they handle IEEE subnormals properly, and their "n" versions
 *	operate speedily on arrays.
 */
/* $Id: ncx.m4 2795 2014-10-27 23:12:51Z wkliao $ */

/*
 * An external data representation interface.
 */

#pragma GCC diagnostic ignored "-Wdeprecated"

#include "ncx.h"
#include "nc3dispatch.h"
#include <string.h>
#include <limits.h>

/* alias poorly named limits.h macros */
#define  SHORT_MAX  SHRT_MAX
#define  SHORT_MIN  SHRT_MIN
#define USHORT_MAX USHRT_MAX
#ifndef LLONG_MAX
#   define LLONG_MAX	9223372036854775807LL
#   define LLONG_MIN	(-LLONG_MAX - 1LL)
#   define ULLONG_MAX	18446744073709551615ULL
#endif
#ifndef LONG_LONG_MAX
#define LONG_LONG_MAX LLONG_MAX
#endif
#ifndef LONGLONG_MAX
#define LONGLONG_MAX LONG_LONG_MAX
#endif
#ifndef LONG_LONG_MIN
#define LONG_LONG_MIN LLONG_MIN
#endif
#ifndef LONGLONG_MIN
#define LONGLONG_MIN LONG_LONG_MIN
#endif
#ifndef ULONG_LONG_MAX
#define ULONG_LONG_MAX ULLONG_MAX
#endif
#ifndef ULONGLONG_MAX
#define ULONGLONG_MAX ULONG_LONG_MAX
#endif
#include <float.h>
#ifndef FLT_MAX /* This POSIX macro missing on some systems */
# ifndef NO_IEEE_FLOAT
# define FLT_MAX 3.40282347e+38f
# else
# error "You will need to define FLT_MAX"
# endif
#endif
/* alias poorly named float.h macros */
#define FLOAT_MAX FLT_MAX
#define FLOAT_MIN (-FLT_MAX)
#define DOUBLE_MAX DBL_MAX
#define DOUBLE_MIN (-DBL_MAX)
#define FLOAT_MAX_EXP FLT_MAX_EXP
#define DOUBLE_MAX_EXP DBL_MAX_EXP
#include <assert.h>
#define UCHAR_MIN 0
#define Min(a,b) ((a) < (b) ? (a) : (b))
#define Max(a,b) ((a) > (b) ? (a) : (b))

#ifndef SIZEOF_USHORT
#define SIZEOF_USHORT SIZEOF_UNSIGNED_SHORT_INT
#endif
#ifndef SIZEOF_UINT
#define SIZEOF_UINT SIZEOF_UNSIGNED_INT
#endif
#ifndef SIZEOF_ULONG_LONG
#define SIZEOF_ULONG_LONG SIZEOF_UNSIGNED_LONG_LONG
#endif

/*
 * If the machine's float domain is "smaller" than the external one
 * use the machine domain
 */
#if defined(FLT_MAX_EXP) && FLT_MAX_EXP < 128 /* 128 is X_FLT_MAX_EXP */
#undef X_FLOAT_MAX
# define X_FLOAT_MAX FLT_MAX
#undef X_FLOAT_MIN
# define X_FLOAT_MIN (-X_FLOAT_MAX)
#endif

#if _SX /* NEC SUPER UX */
#define LOOPCNT 256    /* must be no longer than hardware vector length */
#if _INT64
#undef  INT_MAX /* workaround cpp bug */
#define INT_MAX  X_INT_MAX
#undef  INT_MIN /* workaround cpp bug */
#define INT_MIN  X_INT_MIN
#undef  LONG_MAX /* workaround cpp bug */
#define LONG_MAX  X_INT_MAX
#undef  LONG_MIN /* workaround cpp bug */
#define LONG_MIN  X_INT_MIN
#elif _LONG64
#undef  LONG_MAX /* workaround cpp bug */
#define LONG_MAX  4294967295L
#undef  LONG_MIN /* workaround cpp bug */
#define LONG_MIN -4294967295L
#endif
#if !_FLOAT0
#error "FLOAT1 and FLOAT2 not supported"
#endif
#endif /* _SX */

static const char nada[X_ALIGN] = {0, 0, 0, 0};

#ifndef WORDS_BIGENDIAN
/* LITTLE_ENDIAN: DEC and intel */
/*
 * Routines to convert to BIGENDIAN.
 * Optimize the swapn?b() and swap?b() routines aggressivly.
 */

#define SWAP2(a) ( (((a) & 0xff) << 8) | \
		(((a) >> 8) & 0xff) )

#define SWAP4(a) ( ((a) << 24) | \
		(((a) <<  8) & 0x00ff0000) | \
		(((a) >>  8) & 0x0000ff00) | \
		(((a) >> 24) & 0x000000ff) )


static void
swapn2b(void *dst, const void *src, size_t nn)
{
	char *op = dst;
	const char *ip = src;

/* unroll the following to reduce loop overhead
 *
 *	while(nn-- != 0)
 *	{
 *		*op++ = *(++ip);
 *		*op++ = *(ip++ -1);
 *	}
 */
	while(nn > 3)
	{
		*op++ = *(++ip);
		*op++ = *(ip++ -1);
		*op++ = *(++ip);
		*op++ = *(ip++ -1);
		*op++ = *(++ip);
		*op++ = *(ip++ -1);
		*op++ = *(++ip);
		*op++ = *(ip++ -1);
		nn -= 4;
	}
	while(nn-- > 0)
	{
		*op++ = *(++ip);
		*op++ = *(ip++ -1);
	}
}

# ifndef vax
void
swap4b(void *dst, const void *src)
{
    unsigned int *op = dst;
    const char *ip = src;
    unsigned int tempIn;
    unsigned int tempOut;

    tempIn = *(unsigned int *)(ip+0);
    tempOut =
    ( tempIn << 24) |
    ((tempIn & 0x0000ff00) << 8) |
    ((tempIn & 0x00ff0000) >> 8) |
    ( tempIn >> 24);

    *(float *)op = *(float *)(&tempOut);
}
# endif /* !vax */

static void
swapn4b(void *dst, const void *src, size_t nn)
{
	char *op = dst;
	const char *ip = src;

/* unroll the following to reduce loop overhead
 *	while(nn-- != 0)
 *	{
 *		op[0] = ip[3];
 *		op[1] = ip[2];
 *		op[2] = ip[1];
 *		op[3] = ip[0];
 *		op += 4;
 *		ip += 4;
 *	}
 */
	while(nn > 3)
	{
		op[0] = ip[3];
		op[1] = ip[2];
		op[2] = ip[1];
		op[3] = ip[0];
		op[4] = ip[7];
		op[5] = ip[6];
		op[6] = ip[5];
		op[7] = ip[4];
		op[8] = ip[11];
		op[9] = ip[10];
		op[10] = ip[9];
		op[11] = ip[8];
		op[12] = ip[15];
		op[13] = ip[14];
		op[14] = ip[13];
		op[15] = ip[12];
		op += 16;
		ip += 16;
		nn -= 4;
	}
	while(nn-- > 0)
	{
		op[0] = ip[3];
		op[1] = ip[2];
		op[2] = ip[1];
		op[3] = ip[0];
		op += 4;
		ip += 4;
	}
}

# ifndef vax
static void
swap8b(void *dst, const void *src)
{
	char *op = dst;
	const char *ip = src;
#  ifndef FLOAT_WORDS_BIGENDIAN
	op[0] = ip[7];
	op[1] = ip[6];
	op[2] = ip[5];
	op[3] = ip[4];
	op[4] = ip[3];
	op[5] = ip[2];
	op[6] = ip[1];
	op[7] = ip[0];
#  else
	op[0] = ip[3];
	op[1] = ip[2];
	op[2] = ip[1];
	op[3] = ip[0];
	op[4] = ip[7];
	op[5] = ip[6];
	op[6] = ip[5];
	op[7] = ip[4];
#  endif
}
# endif /* !vax */

# ifndef vax
static void
swapn8b(void *dst, const void *src, size_t nn)
{
	char *op = dst;
	const char *ip = src;

/* unroll the following to reduce loop overhead
 *	while(nn-- != 0)
 *	{
 *		op[0] = ip[7];
 *		op[1] = ip[6];
 *		op[2] = ip[5];
 *		op[3] = ip[4];
 *		op[4] = ip[3];
 *		op[5] = ip[2];
 *		op[6] = ip[1];
 *		op[7] = ip[0];
 *		op += 8;
 *		ip += 8;
 *	}
 */
#  ifndef FLOAT_WORDS_BIGENDIAN
	while(nn > 1)
	{
		op[0] = ip[7];
		op[1] = ip[6];
		op[2] = ip[5];
		op[3] = ip[4];
		op[4] = ip[3];
		op[5] = ip[2];
		op[6] = ip[1];
		op[7] = ip[0];
		op[8] = ip[15];
		op[9] = ip[14];
		op[10] = ip[13];
		op[11] = ip[12];
		op[12] = ip[11];
		op[13] = ip[10];
		op[14] = ip[9];
		op[15] = ip[8];
		op += 16;
		ip += 16;
		nn -= 2;
	}
	while(nn-- != 0)
	{
		op[0] = ip[7];
		op[1] = ip[6];
		op[2] = ip[5];
		op[3] = ip[4];
		op[4] = ip[3];
		op[5] = ip[2];
		op[6] = ip[1];
		op[7] = ip[0];
		op += 8;
		ip += 8;
	}
#  else
	while(nn-- != 0)
	{
		op[0] = ip[3];
		op[1] = ip[2];
		op[2] = ip[1];
		op[3] = ip[0];
		op[4] = ip[7];
		op[5] = ip[6];
		op[6] = ip[5];
		op[7] = ip[4];
		op += 8;
		ip += 8;
	}
#  endif
}
# endif /* !vax */

#endif /* LITTLE_ENDIAN */

dnl dnl dnl
dnl
dnl Upcase(str)
dnl
define(`Upcase',dnl
`dnl
translit($1, abcdefghijklmnopqrstuvwxyz, ABCDEFGHIJKLMNOPQRSTUVWXYZ)')dnl
dnl
dnl dnl dnl
dnl
define(`Isizeof',     ``SIZEOF_'Upcase($1)')dnl
define(`Xsizeof',   ``X_SIZEOF_'Upcase($1)')dnl
define(`IXsizeof', ``SIZEOF_IX_'Upcase($1)')dnl
define(`Imax',                 `Upcase($1)`_MAX'')dnl
define(`Imin',                 `Upcase($1)`_MIN'')dnl
define(`Xmax',             ``X_'Upcase($1)`_MAX'')dnl
define(`Xmin',             ``X_'Upcase($1)`_MIN'')dnl
define(`IXmax',           ``IX_'Upcase($1)`_MAX'')dnl
dnl
define(`Fmin',  `ifelse(index(`$1',`u'), 0, `0', `(double)Imin($1)')')dnl
define(`Dmin',  `ifelse(index(`$1',`u'), 0, `0',         `Imin($1)')')dnl
define(`FXmin', `ifelse(index(`$1',`u'), 0, `0', `(double)Xmin($1)')')dnl
define(`DXmin', `ifelse(index(`$1',`u'), 0, `0',         `Xmin($1)')')dnl

dnl
dnl For GET APIs:
dnl       check for negative xx if xp is   signed && ip is unsigned
dnl Don't check for negative xx if xp is   signed && ip is   signed
dnl Don't check for negative xx if xp is unsigned
dnl
define(`GETI_CheckNeg', `ifelse(index(`$1',`u'), 0, , `ifelse(index(`$2',`u'), 0, `	if (xx < 0) return NC_ERANGE; /* because ip is unsigned */')')')dnl

dnl
dnl For PUT APIs:
dnl       check for negative ip if xp is unsigned && ip is   signed
dnl Don't check for negative ip if xp is unsigned && ip is unsigned
dnl Don't check for negative ip if xp is   signed
dnl
define(`PUTI_CheckNeg', `ifelse(index(`$1',`u'), 0, `ifelse(index(`$2',`u'), 0, , `	if (*ip < 0) return NC_ERANGE; /* because xp is unsigned */')')')dnl

dnl
dnl For GET APIs and either $1 and $2 is float or double:
dnl
define(`GETF_CheckBND',
`ifelse(`$1', `double', `	if(xx > Upcase($2)_MAX || xx < Dmin($2)) return NC_ERANGE;',
		       `ifelse(`$1', `float', `ifelse(`$2', `double',,`	if(xx > (double)Upcase($2)_MAX || xx < Fmin($2)) return NC_ERANGE;')')'dnl
)')

dnl
dnl For PUT APIs and either $1 and $2 is float or double:
dnl
define(`PUTF_CheckBND',
`ifelse(`$2', `double', `	if(*ip > Xmax($1) || *ip < DXmin($1)) return NC_ERANGE;',
		       `ifelse(`$2', `float', `	if(*ip > (double)Xmax($1) || *ip < FXmin($1)) return NC_ERANGE;')'dnl
)')

dnl
dnl For GET APIs and $1 and $2 are not float or double
dnl
define(`GETI_CheckBND',
``#'if IXmax($1) > Imax($2)
	if (xx > Imax($2)'`ifelse(index(`$1',`u'), 0, , `ifelse(index(`$2',`u'), 0, , ` || xx < Imin($2)')')'`) return NC_ERANGE;'
`#'endif)

dnl
dnl For PUT APIs and $1 and $2 are not float or double
dnl
define(`PUTI_CheckBND',
``#'if IXmax($1) < Imax($2)
	if (*ip > IXmax($1)'`ifelse(index(`$1',`u'), 0, , `ifelse(index(`$2',`u'), 0, , ` || *ip < Xmin($1)')')'`) return NC_ERANGE;'
`#'endif)

/*
 * Primitive numeric conversion functions.
 */

dnl dnl dnl
dnl
dnl NCX_GET1F(xtype, itype) for floating-point types
dnl
define(`NCX_GET1F',dnl
`dnl
int
ncx_get_$1_$2(const void *xp, $2 *ip)
{
	ix_$1 xx;
	get_ix_$1(xp, &xx);
	*ip = ($2) xx;
GETF_CheckBND($1, $2)
	return ENOERR;
}
')dnl

dnl dnl dnl
dnl
dnl NCX_GET1I(xtype, itype, isComptable) for integral types
dnl
define(`NCX_GET1I',dnl
`dnl
int
ncx_get_$1_$2(const void *xp, $2 *ip)
{
ifelse(`$3', `1',
``#'if IXsizeof($1) == Isizeof($2) && IXmax($1) == Upcase($2)_MAX
	get_ix_$1(xp, (ix_$1 *)ip);
	return ENOERR;
`#'else
')dnl
	ix_$1 xx;
	get_ix_$1(xp, &xx);
	*ip = ($2) xx;
GETI_CheckBND($1, $2)
GETI_CheckNeg($1, $2)
ifelse(`$3', `1', ``#'endif
')dnl
	return ENOERR;
}
')dnl

dnl dnl dnl
dnl
dnl NCX_PUT1F(xtype, itype) for floating-point types
dnl
define(`NCX_PUT1F',dnl
`dnl
int
ncx_put_$1_$2(void *xp, const $2 *ip)
{
	ix_$1 xx = (ix_$1)*ip;
	put_ix_$1(xp, &xx);
PUTF_CheckBND($1, $2)
	return ENOERR;
}
')dnl

dnl dnl dnl
dnl
dnl NCX_PUT1I(xtype, itype, isComptable) for integral types
dnl
define(`NCX_PUT1I',dnl
`dnl
int
ncx_put_$1_$2(void *xp, const $2 *ip)
{
ifelse(`$3', `1',
``#'if IXsizeof($1) == Isizeof($2) && IXmax($1) == Upcase($2)_MAX
	put_ix_$1(xp, (const ix_$1 *)ip);
	return ENOERR;
`#'else
')dnl
	ix_$1 xx = (ix_$1)*ip;
	put_ix_$1(xp, &xx);
PUTI_CheckBND($1, $2)
PUTI_CheckNeg($1, $2)
ifelse(`$3', `1', ``#'endif
')dnl
	return ENOERR;
}
')dnl

/* x_schar */
/* x_uchar */

/* We don't implement any x_schar and x_uchar primitives. */


/* x_short -------------------------------------------------------------------*/

#if SHORT_MAX == X_SHORT_MAX
typedef short ix_short;
#define SIZEOF_IX_SHORT SIZEOF_SHORT
#define IX_SHORT_MAX SHORT_MAX
#elif INT_MAX >= X_SHORT_MAX
typedef int ix_short;
#define SIZEOF_IX_SHORT SIZEOF_INT
#define IX_SHORT_MAX INT_MAX
#elif LONG_MAX >= X_SHORT_MAX
typedef long ix_short;
#define SIZEOF_IX_SHORT SIZEOF_LONG
#define IX_SHORT_MAX LONG_MAX
#elif LLONG_MAX >= X_SHORT_MAX
typedef long long ix_short;
#define SIZEOF_IX_SHORT SIZEOF_LONG_LONG
#define IX_SHORT_MAX LLONG_MAX
#else
#error "ix_short implementation"
#endif

static void
get_ix_short(const void *xp, ix_short *ip)
{
	const uchar *cp = (const uchar *) xp;
	*ip = *cp++ << 8;
#if SIZEOF_IX_SHORT > X_SIZEOF_SHORT
	if(*ip & 0x8000)
	{
		/* extern is negative */
		*ip |= (~(0xffff)); /* N.B. Assumes "twos complement" */
	}
#endif
	*ip |= *cp;
}

static void
put_ix_short(void *xp, const ix_short *ip)
{
	uchar *cp = (uchar *) xp;
	*cp++ = (*ip) >> 8;
	*cp = (*ip) & 0xff;
}

static NCX_GET1I(short, schar,     0)
static NCX_GET1I(short, short,     1)
static NCX_GET1I(short, int,       1)
static NCX_GET1I(short, longlong,  1)
static NCX_GET1I(short, ushort,    0)
static NCX_GET1I(short, uchar,     0)
static NCX_GET1I(short, uint,      0)
static NCX_GET1I(short, ulonglong, 0)
static NCX_GET1F(short, float)
static NCX_GET1F(short, double)

static int
ncx_put_short_schar(void *xp, const schar *ip)
{
	uchar *cp = (uchar *) xp;
	if(*ip & 0x80)
		*cp++ = 0xff;
	else
		*cp++ = 0;
	*cp = (uchar)*ip;
	return ENOERR;
}

static int
ncx_put_short_uchar(void *xp, const uchar *ip)
{
	uchar *cp = (uchar *) xp;
	*cp++ = 0;
	*cp = *ip;
	return ENOERR;
}

static NCX_PUT1I(short, short,     1)
static NCX_PUT1I(short, int,       1)
static NCX_PUT1I(short, longlong,  1)
static NCX_PUT1I(short, ushort,    0)
static NCX_PUT1I(short, uint,      0)
static NCX_PUT1I(short, ulonglong, 0)
static NCX_PUT1F(short, float)
static NCX_PUT1F(short, double)

/* x_ushort ------------------------------------------------------------------*/

#if USHORT_MAX == X_USHORT_MAX
typedef unsigned short ix_ushort;
#define SIZEOF_IX_USHORT SIZEOF_USHORT
#define IX_USHORT_MAX USHORT_MAX
#elif UINT_MAX >= X_USHORT_MAX
typedef unsigned int ix_ushort;
#define SIZEOF_IX_USHORT SIZEOF_UINT
#define IX_USHORT_MAX UINT_MAX
#elif ULONG_MAX >= X_USHORT_MAX
typedef unsigned long ix_ushort;
#define SIZEOF_IX_USHORT SIZEOF_ULONG
#define IX_USHORT_MAX ULONG_MAX
#elif ULLONG_MAX >= X_USHORT_MAX
typedef unsigned long long ix_ushort;
#define SIZEOF_IX_USHORT SIZEOF_ULONG_LONG
#define IX_USHORT_MAX ULLONG_MAX
#else
#error "ix_ushort implementation"
#endif

static void
get_ix_ushort(const void *xp, ix_ushort *ip)
{
	const uchar *cp = (const uchar *) xp;
	*ip = *cp++ << 8;
#if SIZEOF_IX_SHORT > X_SIZEOF_SHORT
	if(*ip & 0x8000)
	{
		/* extern is negative */
		*ip |= (~(0xffff)); /* N.B. Assumes "twos complement" */
	}
#endif
	*ip |= *cp; 
}

static void
put_ix_ushort(void *xp, const ix_ushort *ip)
{
	uchar *cp = (uchar *) xp;
	*cp++ = (*ip) >> 8;
	*cp = (*ip) & 0xff;
}

static NCX_GET1I(ushort, schar,     0)
static NCX_GET1I(ushort, short,     0)
static NCX_GET1I(ushort, int,       0)
static NCX_GET1I(ushort, longlong,  0)
static NCX_GET1I(ushort, ushort,    1)
static NCX_GET1I(ushort, uchar,     1)
static NCX_GET1I(ushort, uint,      1)
static NCX_GET1I(ushort, ulonglong, 1)
static NCX_GET1F(ushort, float)
static NCX_GET1F(ushort, double)

static int
ncx_put_ushort_schar(void *xp, const schar *ip)
{
	uchar *cp = (uchar *) xp;
	if(*ip & 0x80)
		*cp++ = 0xff;
	else
		*cp++ = 0;
	*cp = (uchar)*ip;
        if (*ip < 0) return NC_ERANGE;

	return ENOERR;
}

static int
ncx_put_ushort_uchar(void *xp, const uchar *ip)
{
	uchar *cp = (uchar *) xp;
	*cp++ = 0;
	*cp = *ip;
	return ENOERR;
}

static NCX_PUT1I(ushort, short,     0)
static NCX_PUT1I(ushort, int,       0)
static NCX_PUT1I(ushort, longlong,  0)
static NCX_PUT1I(ushort, ushort,    1)
static NCX_PUT1I(ushort, uint,      1)
static NCX_PUT1I(ushort, ulonglong, 1)
static NCX_PUT1F(ushort, float)
static NCX_PUT1F(ushort, double)

/* x_int ---------------------------------------------------------------------*/

#if SHORT_MAX == X_INT_MAX
typedef short ix_int;
#define SIZEOF_IX_INT SIZEOF_SHORT
#define IX_INT_MAX SHORT_MAX
#elif INT_MAX  >= X_INT_MAX
typedef int ix_int;
#define SIZEOF_IX_INT SIZEOF_INT
#define IX_INT_MAX INT_MAX
#elif LONG_MAX  >= X_INT_MAX
typedef long ix_int;
#define SIZEOF_IX_INT SIZEOF_LONG
#define IX_INT_MAX LONG_MAX
#else
#error "ix_int implementation"
#endif


static void
get_ix_int(const void *xp, ix_int *ip)
{
	const uchar *cp = (const uchar *) xp;

	*ip = *cp++ << 24;
#if SIZEOF_IX_INT > X_SIZEOF_INT
	if(*ip & 0x80000000)
	{
		/* extern is negative */
		*ip |= (~(0xffffffff)); /* N.B. Assumes "twos complement" */
	}
#endif
	*ip |= (*cp++ << 16);
	*ip |= (*cp++ << 8);
	*ip |= *cp;
}

static void
put_ix_int(void *xp, const ix_int *ip)
{
	uchar *cp = (uchar *) xp;

	*cp++ = (*ip) >> 24;
	*cp++ = ((*ip) & 0x00ff0000) >> 16;
	*cp++ = ((*ip) & 0x0000ff00) >>  8;
	*cp   = ((*ip) & 0x000000ff);
}

static NCX_GET1I(int, schar,     0)
static NCX_GET1I(int, short,     1)
       NCX_GET1I(int, int,       1)
static NCX_GET1I(int, longlong,  1)
static NCX_GET1I(int, ushort,    0)
static NCX_GET1I(int, uchar,     0)
static NCX_GET1I(int, uint,      0)
static NCX_GET1I(int, ulonglong, 0)
static NCX_GET1F(int, float)
static NCX_GET1F(int, double)

static int
ncx_put_int_schar(void *xp, const schar *ip)
{
	uchar *cp = (uchar *) xp;
	if(*ip & 0x80)
	{
		*cp++ = 0xff;
		*cp++ = 0xff;
		*cp++ = 0xff;
	}
	else
	{
		*cp++ = 0x00;
		*cp++ = 0x00;
		*cp++ = 0x00;
	}
	*cp = (uchar)*ip;
	return ENOERR;
}

static int
ncx_put_int_uchar(void *xp, const uchar *ip)
{
	uchar *cp = (uchar *) xp;
	*cp++ = 0x00;
	*cp++ = 0x00;
	*cp++ = 0x00;
	*cp   = *ip;
	return ENOERR;
}

static NCX_PUT1I(int, short,     1)
       NCX_PUT1I(int, int,       1)
static NCX_PUT1I(int, longlong,  1)
static NCX_PUT1I(int, ushort,    0)
static NCX_PUT1I(int, uint,      0)
static NCX_PUT1I(int, ulonglong, 0)
static NCX_PUT1F(int, float)
static NCX_PUT1F(int, double)


/* x_uint --------------------------------------------------------------------*/

#if USHORT_MAX == X_UINT_MAX
typedef ushort ix_uint;
#define SIZEOF_IX_UINT SIZEOF_USHORT
#define IX_UINT_MAX USHORT_MAX
#elif UINT_MAX  >= X_UINT_MAX
typedef uint ix_uint;
#define SIZEOF_IX_UINT SIZEOF_UINT
#define IX_UINT_MAX UINT_MAX
#elif ULONG_MAX  >= X_UINT_MAX
typedef ulong ix_uint;
#define SIZEOF_IX_UINT SIZEOF_ULONG
#define IX_UINT_MAX ULONG_MAX
#else
#error "ix_uint implementation"
#endif


static void
get_ix_uint(const void *xp, ix_uint *ip)
{
	const uchar *cp = (const uchar *) xp;

	*ip = *cp++ << 24;
	*ip |= (*cp++ << 16);
	*ip |= (*cp++ << 8);
	*ip |= *cp; 
}

static void
put_ix_uint(void *xp, const ix_uint *ip)
{
	uchar *cp = (uchar *) xp;

	*cp++ = (*ip) >> 24;
	*cp++ = ((*ip) & 0x00ff0000) >> 16;
	*cp++ = ((*ip) & 0x0000ff00) >>  8;
	*cp   = ((*ip) & 0x000000ff);
}

#if X_SIZEOF_UINT != SIZEOF_UINT
static NCX_GET1I(uint, uint,      1)
#endif

static NCX_GET1I(uint, schar,     0)
static NCX_GET1I(uint, short,     0)
static NCX_GET1I(uint, int,       0)
static NCX_GET1I(uint, longlong,  0)
static NCX_GET1I(uint, ushort,    1)
static NCX_GET1I(uint, uchar,     1)
static NCX_GET1I(uint, ulonglong, 1)
static NCX_GET1F(uint, float)
static NCX_GET1F(uint, double)

static int
ncx_put_uint_schar(void *xp, const schar *ip)
{
	uchar *cp = (uchar *) xp;
	*cp++ = 0x00;
	*cp++ = 0x00;
	*cp++ = 0x00;
	*cp = (uchar)*ip;

	if (*ip < 0) return NC_ERANGE;

	return ENOERR;
}

static int
ncx_put_uint_uchar(void *xp, const uchar *ip)
{
	uchar *cp = (uchar *) xp;
	*cp++ = 0x00;
	*cp++ = 0x00;
	*cp++ = 0x00;
	*cp   = *ip;
	return ENOERR;
}

#if X_SIZEOF_UINT != SIZEOF_UINT
static NCX_PUT1I(uint, uint,      1)
#endif

static NCX_PUT1I(uint, short,     0)
static NCX_PUT1I(uint, int,       0)
static NCX_PUT1I(uint, longlong,  0)
static NCX_PUT1I(uint, ushort,    1)
static NCX_PUT1I(uint, ulonglong, 1)
static NCX_PUT1F(uint, float)
static NCX_PUT1F(uint, double)

/* x_float -------------------------------------------------------------------*/

#if X_SIZEOF_FLOAT == SIZEOF_FLOAT && !defined(NO_IEEE_FLOAT)

static void
get_ix_float(const void *xp, float *ip)
{
#ifdef WORDS_BIGENDIAN
	(void) memcpy(ip, xp, sizeof(float));
#else
	swap4b(ip, xp);
#endif
}

static void
put_ix_float(void *xp, const float *ip)
{
#ifdef WORDS_BIGENDIAN
	(void) memcpy(xp, ip, X_SIZEOF_FLOAT);
#else
	swap4b(xp, ip);
#endif
}

#elif vax

/* What IEEE single precision floating point looks like on a Vax */
struct	ieee_single {
	unsigned int	exp_hi       : 7;
	unsigned int	sign         : 1;
	unsigned int 	mant_hi      : 7;
	unsigned int	exp_lo       : 1;
	unsigned int	mant_lo_hi   : 8;
	unsigned int	mant_lo_lo   : 8;
};

/* Vax single precision floating point */
struct	vax_single {
	unsigned int	mantissa1 : 7;
	unsigned int	exp       : 8;
	unsigned int	sign      : 1;
	unsigned int	mantissa2 : 16;
};

#define VAX_SNG_BIAS	0x81
#define IEEE_SNG_BIAS	0x7f

static struct sgl_limits {
	struct vax_single s;
	struct ieee_single ieee;
} max = {
	{ 0x7f, 0xff, 0x0, 0xffff },	/* Max Vax */
	{ 0x7f, 0x0, 0x0, 0x1, 0x0, 0x0 }		/* Max IEEE */
};
static struct sgl_limits min = {
	{ 0x0, 0x0, 0x0, 0x0 },	/* Min Vax */
	{ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0 }		/* Min IEEE */
};

dnl dnl dnl
dnl
dnl GET_VAX_DFLOAT_Body(xp) (body for get_ix_float)
dnl
define(`GET_VAX_DFLOAT_Body',dnl
`dnl
		struct vax_single *const vsp = (struct vax_single *) ip;
		const struct ieee_single *const isp =
			 (const struct ieee_single *) $1;
		unsigned exp = isp->exp_hi << 1 | isp->exp_lo;

		switch(exp) {
		case 0 :
			/* ieee subnormal */
			if(isp->mant_hi == min.ieee.mant_hi
				&& isp->mant_lo_hi == min.ieee.mant_lo_hi
				&& isp->mant_lo_lo == min.ieee.mant_lo_lo)
			{
				*vsp = min.s;
			}
			else
			{
				unsigned mantissa = (isp->mant_hi << 16)
					 | isp->mant_lo_hi << 8
					 | isp->mant_lo_lo;
				unsigned tmp = mantissa >> 20;
				if(tmp >= 4) {
					vsp->exp = 2;
				} else if (tmp >= 2) {
					vsp->exp = 1;
				} else {
					*vsp = min.s;
					break;
				} /* else */
				tmp = mantissa - (1 << (20 + vsp->exp ));
				tmp <<= 3 - vsp->exp;
				vsp->mantissa2 = tmp;
				vsp->mantissa1 = (tmp >> 16);
			}
			break;
		case 0xfe :
		case 0xff :
			*vsp = max.s;
			break;
		default :
			vsp->exp = exp - IEEE_SNG_BIAS + VAX_SNG_BIAS;
			vsp->mantissa2 = isp->mant_lo_hi << 8 | isp->mant_lo_lo;
			vsp->mantissa1 = isp->mant_hi;
		}

		vsp->sign = isp->sign;
')dnl
static void
get_ix_float(const void *xp, float *ip)
{
GET_VAX_DFLOAT_Body(xp)
}

dnl dnl dnl
dnl
dnl PUT_VAX_DFLOAT_Body(xp) (body for get_ix_float)
dnl
define(`PUT_VAX_DFLOAT_Body',dnl
`dnl
		const struct vax_single *const vsp =
			 (const struct vax_single *)ip;
		struct ieee_single *const isp = (struct ieee_single *) $1;

		switch(vsp->exp){
		case 0 :
			/* all vax float with zero exponent map to zero */
			*isp = min.ieee;
			break;
		case 2 :
		case 1 :
		{
			/* These will map to subnormals */
			unsigned mantissa = (vsp->mantissa1 << 16)
					 | vsp->mantissa2;
			mantissa >>= 3 - vsp->exp;
			mantissa += (1 << (20 + vsp->exp));
			isp->mant_lo_lo = mantissa;
			isp->mant_lo_hi = mantissa >> 8;
			isp->mant_hi = mantissa >> 16;
			isp->exp_lo = 0;
			isp->exp_hi = 0;
		}
			break;
		case 0xff : /* max.s.exp */
			if( vsp->mantissa2 == max.s.mantissa2
				&& vsp->mantissa1 == max.s.mantissa1)
			{
				/* map largest vax float to ieee infinity */
				*isp = max.ieee;
				break;
			} /* else, fall thru */
		default :
		{
			unsigned exp = vsp->exp - VAX_SNG_BIAS + IEEE_SNG_BIAS;
			isp->exp_hi = exp >> 1;
			isp->exp_lo = exp;
			isp->mant_lo_lo = vsp->mantissa2;
			isp->mant_lo_hi = vsp->mantissa2 >> 8;
			isp->mant_hi = vsp->mantissa1;
		}
		}

		isp->sign = vsp->sign;
')dnl

static void
put_ix_float(void *xp, const float *ip)
{
PUT_VAX_DFLOAT_Body(xp)
}

	/* vax */
#elif defined(_CRAY) && !defined(__crayx1)

/*
 * Return the number of bytes until the next "word" boundary
 * N.B. This is based on the very weird YMP address structure,
 * which puts the address within a word in the leftmost 3 bits
 * of the address.
 */
static size_t
word_align(const void *vp)
{
	const size_t rem = ((size_t)vp >> (64 - 3)) & 0x7;
	return (rem != 0);
}

struct ieee_single_hi {
	unsigned int	sign	: 1;
	unsigned int	 exp	: 8;
	unsigned int	mant	:23;
	unsigned int	pad	:32;
};
typedef struct ieee_single_hi ieee_single_hi;

struct ieee_single_lo {
	unsigned int	pad	:32;
	unsigned int	sign	: 1;
	unsigned int	 exp	: 8;
	unsigned int	mant	:23;
};
typedef struct ieee_single_lo ieee_single_lo;

static const int ieee_single_bias = 0x7f;

struct ieee_double {
	unsigned int	sign	: 1;
	unsigned int	 exp	:11;
	unsigned int	mant	:52;
};
typedef struct ieee_double ieee_double;

static const int ieee_double_bias = 0x3ff;

#if defined(NO_IEEE_FLOAT)

struct cray_single {
	unsigned int	sign	: 1;
	unsigned int	 exp	:15;
	unsigned int	mant	:48;
};
typedef struct cray_single cray_single;

static const int cs_ieis_bias = 0x4000 - 0x7f;

static const int cs_id_bias = 0x4000 - 0x3ff;

dnl dnl dnl
dnl
dnl GET_IX_FLOAT_Body (body for get_ix_float)
dnl
define(`GET_IX_FLOAT_Body',dnl
`dnl
		cray_single *csp = (cray_single *) ip;

		if(isp->exp == 0)
		{
			/* ieee subnormal */
			*ip = (double)isp->mant;
			if(isp->mant != 0)
			{
				csp->exp -= (ieee_single_bias + 22);
			}
		}
		else
		{
			csp->exp  = isp->exp + cs_ieis_bias + 1;
			csp->mant = isp->mant << (48 - 1 - 23);
			csp->mant |= (1 << (48 - 1));
		}
		csp->sign = isp->sign;

')dnl
dnl dnl dnl
dnl
dnl PUT_IX_FLOAT_Body (body for put_ix_float)
dnl
define(`PUT_IX_FLOAT_Body',dnl
`dnl
	const cray_single *csp = (const cray_single *) ip;
	int ieee_exp = csp->exp - cs_ieis_bias -1;

	isp->sign = csp->sign;

	if(ieee_exp >= 0xff)
	{
		/* NC_ERANGE => ieee Inf */
		isp->exp = 0xff;
		isp->mant = 0x0;
	}
	else if(ieee_exp > 0)
	{
		/* normal ieee representation */
		isp->exp  = ieee_exp;
		/* assumes cray rep is in normal form */
		assert(csp->mant & 0x800000000000);
		isp->mant = (((csp->mant << 1) &
				0xffffffffffff) >> (48 - 23));
	}
	else if(ieee_exp > -23)
	{
		/* ieee subnormal, right shift */
		const int rshift = (48 - 23 - ieee_exp);

		isp->mant = csp->mant >> rshift;

#if 0
		if(csp->mant & (1 << (rshift -1)))
		{
			/* round up */
			isp->mant++;
		}
#endif

		isp->exp  = 0;
	}
	else
	{
		/* smaller than ieee can represent */
		isp->exp = 0;
		isp->mant = 0;
	}
')dnl

static void
get_ix_float(const void *xp, float *ip)
{

	if(word_align(xp) == 0)
	{
		const ieee_single_hi *isp = (const ieee_single_hi *) xp;
GET_IX_FLOAT_Body
	}
	else
	{
		const ieee_single_lo *isp = (const ieee_single_lo *) xp;
GET_IX_FLOAT_Body
	}
}

static void
put_ix_float(void *xp, const float *ip)
{
	if(word_align(xp) == 0)
	{
		ieee_single_hi *isp = (ieee_single_hi*)xp;
PUT_IX_FLOAT_Body
	}
	else
	{
		ieee_single_lo *isp = (ieee_single_lo*)xp;
PUT_IX_FLOAT_Body
	}
}

#else
	/* IEEE Cray with only doubles */
static void
get_ix_float(const void *xp, float *ip)
{

	ieee_double *idp = (ieee_double *) ip;

	if(word_align(xp) == 0)
	{
		const ieee_single_hi *isp = (const ieee_single_hi *) xp;
		if(isp->exp == 0 && isp->mant == 0)
		{
			idp->exp = 0;
			idp->mant = 0;
		}
		else
		{
			idp->exp = isp->exp + (ieee_double_bias - ieee_single_bias);
			idp->mant = isp->mant << (52 - 23);
		}
		idp->sign = isp->sign;
	}
	else
	{
		const ieee_single_lo *isp = (const ieee_single_lo *) xp;
		if(isp->exp == 0 && isp->mant == 0)
		{
			idp->exp = 0;
			idp->mant = 0;
		}
		else
		{
			idp->exp = isp->exp + (ieee_double_bias - ieee_single_bias);
			idp->mant = isp->mant << (52 - 23);
		}
		idp->sign = isp->sign;
	}
}

static void
put_ix_float(void *xp, const float *ip)
{
	const ieee_double *idp = (const ieee_double *) ip;
	if(word_align(xp) == 0)
	{
		ieee_single_hi *isp = (ieee_single_hi*)xp;
		if(idp->exp > (ieee_double_bias - ieee_single_bias))
			isp->exp = idp->exp - (ieee_double_bias - ieee_single_bias);
		else
			isp->exp = 0;
		isp->mant = idp->mant >> (52 - 23);
		isp->sign = idp->sign;
	}
	else
	{
		ieee_single_lo *isp = (ieee_single_lo*)xp;
		if(idp->exp > (ieee_double_bias - ieee_single_bias))
			isp->exp = idp->exp - (ieee_double_bias - ieee_single_bias);
		else
			isp->exp = 0;
		isp->mant = idp->mant >> (52 - 23);
		isp->sign = idp->sign;
	}
}
#endif

#else
#error "ix_float implementation"
#endif

#if X_SIZEOF_FLOAT != SIZEOF_FLOAT || defined(NO_IEEE_FLOAT)
static int
ncx_get_float_float(const void *xp, float *ip)
{
	/* TODO */
	get_ix_float(xp, ip);
	return ENOERR;
}
#endif

#define ix_float float

static NCX_GET1F(float, schar)
static NCX_GET1F(float, short)
static NCX_GET1F(float, int)
static NCX_GET1F(float, double)
static NCX_GET1F(float, longlong)
static NCX_GET1F(float, uchar)
static NCX_GET1F(float, ushort)
static NCX_GET1F(float, uint)
static NCX_GET1F(float, ulonglong)

#if X_SIZEOF_FLOAT != SIZEOF_FLOAT || defined(NO_IEEE_FLOAT)
static int
ncx_put_float_float(void *xp, const float *ip)
{
	put_ix_float(xp, ip);
#ifdef NO_IEEE_FLOAT
	if(*ip > X_FLOAT_MAX || *ip < X_FLOAT_MIN)
		return NC_ERANGE;
#endif
	return ENOERR;
}
#endif

static NCX_PUT1F(float, schar)
static NCX_PUT1F(float, short)
static NCX_PUT1F(float, int)
static NCX_PUT1F(float, double)
static NCX_PUT1F(float, longlong)
static NCX_PUT1F(float, uchar)
static NCX_PUT1F(float, ushort)
static NCX_PUT1F(float, uint)
static NCX_PUT1F(float, ulonglong)


/* x_double ------------------------------------------------------------------*/

#if X_SIZEOF_DOUBLE == SIZEOF_DOUBLE  && !defined(NO_IEEE_FLOAT)

static void
get_ix_double(const void *xp, double *ip)
{
#ifdef WORDS_BIGENDIAN
	(void) memcpy(ip, xp, sizeof(double));
#else
	swap8b(ip, xp);
#endif
}

static void
put_ix_double(void *xp, const double *ip)
{
#ifdef WORDS_BIGENDIAN
	(void) memcpy(xp, ip, X_SIZEOF_DOUBLE);
#else
	swap8b(xp, ip);
#endif
}

#elif vax

/* What IEEE double precision floating point looks like on a Vax */
struct	ieee_double {
	unsigned int	exp_hi   : 7;
	unsigned int	sign     : 1;
	unsigned int 	mant_6   : 4;
	unsigned int	exp_lo   : 4;
	unsigned int	mant_5   : 8;
	unsigned int	mant_4   : 8;

	unsigned int	mant_lo  : 32;
};

/* Vax double precision floating point */
struct  vax_double {
	unsigned int	mantissa1 : 7;
	unsigned int	exp       : 8;
	unsigned int	sign      : 1;
	unsigned int	mantissa2 : 16;
	unsigned int	mantissa3 : 16;
	unsigned int	mantissa4 : 16;
};

#define VAX_DBL_BIAS	0x81
#define IEEE_DBL_BIAS	0x3ff
#define MASK(nbits)	((1 << nbits) - 1)

static const struct dbl_limits {
	struct	vax_double d;
	struct	ieee_double ieee;
} dbl_limits[2] = {
	{{ 0x7f, 0xff, 0x0, 0xffff, 0xffff, 0xffff },	/* Max Vax */
	{ 0x7f, 0x0, 0x0, 0xf, 0x0, 0x0, 0x0}}, /* Max IEEE */
	{{ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0},		/* Min Vax */
	{ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}}, /* Min IEEE */
};


dnl dnl dnl
dnl
dnl GET_VAX_DDOUBLE_Body(xp) (body for get_ix_double)
dnl
define(`GET_VAX_DDOUBLE_Body',dnl
`dnl
	struct vax_double *const vdp =
			 (struct vax_double *)ip;
	const struct ieee_double *const idp =
			 (const struct ieee_double *) $1;
	{
		const struct dbl_limits *lim;
		int ii;
		for (ii = 0, lim = dbl_limits;
			ii < sizeof(dbl_limits)/sizeof(struct dbl_limits);
			ii++, lim++)
		{
			if ((idp->mant_lo == lim->ieee.mant_lo)
				&& (idp->mant_4 == lim->ieee.mant_4)
				&& (idp->mant_5 == lim->ieee.mant_5)
				&& (idp->mant_6 == lim->ieee.mant_6)
				&& (idp->exp_lo == lim->ieee.exp_lo)
				&& (idp->exp_hi == lim->ieee.exp_hi)
				)
			{
				*vdp = lim->d;
				goto doneit;
			}
		}
	}
	{
		unsigned exp = idp->exp_hi << 4 | idp->exp_lo;
		vdp->exp = exp - IEEE_DBL_BIAS + VAX_DBL_BIAS;
	}
	{
		unsigned mant_hi = ((idp->mant_6 << 16)
				 | (idp->mant_5 << 8)
				 | idp->mant_4);
		unsigned mant_lo = SWAP4(idp->mant_lo);
		vdp->mantissa1 = (mant_hi >> 13);
		vdp->mantissa2 = ((mant_hi & MASK(13)) << 3)
				| (mant_lo >> 29);
		vdp->mantissa3 = (mant_lo >> 13);
		vdp->mantissa4 = (mant_lo << 3);
	}
	doneit:
		vdp->sign = idp->sign;
')dnl
static void
get_ix_double(const void *xp, double *ip)
{
GET_VAX_DDOUBLE_Body(xp)
}


dnl dnl dnl
dnl
dnl PUT_VAX_DDOUBLE_Body(xp) (body for put_ix_double)
dnl
define(`PUT_VAX_DDOUBLE_Body',dnl
`dnl
	const struct vax_double *const vdp =
			(const struct vax_double *)ip;
	struct ieee_double *const idp =
			 (struct ieee_double *) $1;

	if ((vdp->mantissa4 > (dbl_limits[0].d.mantissa4 - 3)) &&
		(vdp->mantissa3 == dbl_limits[0].d.mantissa3) &&
		(vdp->mantissa2 == dbl_limits[0].d.mantissa2) &&
		(vdp->mantissa1 == dbl_limits[0].d.mantissa1) &&
		(vdp->exp == dbl_limits[0].d.exp))
	{
		*idp = dbl_limits[0].ieee;
		goto shipit;
	}
	if ((vdp->mantissa4 == dbl_limits[1].d.mantissa4) &&
		(vdp->mantissa3 == dbl_limits[1].d.mantissa3) &&
		(vdp->mantissa2 == dbl_limits[1].d.mantissa2) &&
		(vdp->mantissa1 == dbl_limits[1].d.mantissa1) &&
		(vdp->exp == dbl_limits[1].d.exp))
	{
		*idp = dbl_limits[1].ieee;
		goto shipit;
	}

	{
		unsigned exp = vdp->exp - VAX_DBL_BIAS + IEEE_DBL_BIAS;

		unsigned mant_lo = ((vdp->mantissa2 & MASK(3)) << 29) |
			(vdp->mantissa3 << 13) |
			((vdp->mantissa4 >> 3) & MASK(13));

		unsigned mant_hi = (vdp->mantissa1 << 13)
				 | (vdp->mantissa2 >> 3);

		if((vdp->mantissa4 & 7) > 4)
		{
			/* round up */
			mant_lo++;
			if(mant_lo == 0)
			{
				mant_hi++;
				if(mant_hi > 0xffffff)
				{
					mant_hi = 0;
					exp++;
				}
			}
		}

		idp->mant_lo = SWAP4(mant_lo);
		idp->mant_6 = mant_hi >> 16;
		idp->mant_5 = (mant_hi & 0xff00) >> 8;
		idp->mant_4 = mant_hi;
		idp->exp_hi = exp >> 4;
		idp->exp_lo = exp;
	}

	shipit:
		idp->sign = vdp->sign;
')dnl
static void
put_ix_double(void *xp, const double *ip)
{
PUT_VAX_DDOUBLE_Body(xp)
}

	/* vax */
#elif defined(_CRAY) && !defined(__crayx1)

static void
get_ix_double(const void *xp, double *ip)
{
	const ieee_double *idp = (const ieee_double *) xp;
	cray_single *csp = (cray_single *) ip;

	if(idp->exp == 0)
	{
		/* ieee subnormal */
		*ip = (double)idp->mant;
		if(idp->mant != 0)
		{
			csp->exp -= (ieee_double_bias + 51);
		}
	}
	else
	{
		csp->exp  = idp->exp + cs_id_bias + 1;
		csp->mant = idp->mant >> (52 - 48 + 1);
		csp->mant |= (1 << (48 - 1));
	}
	csp->sign = idp->sign;
}

static void
put_ix_double(void *xp, const double *ip)
{
	ieee_double *idp = (ieee_double *) xp;
	const cray_single *csp = (const cray_single *) ip;

	int ieee_exp = csp->exp - cs_id_bias -1;

	idp->sign = csp->sign;

	if(ieee_exp >= 0x7ff)
	{
		/* NC_ERANGE => ieee Inf */
		idp->exp = 0x7ff;
		idp->mant = 0x0;
	}
	else if(ieee_exp > 0)
	{
		/* normal ieee representation */
		idp->exp  = ieee_exp;
		/* assumes cray rep is in normal form */
		assert(csp->mant & 0x800000000000);
		idp->mant = (((csp->mant << 1) &
				0xffffffffffff) << (52 - 48));
	}
	else if(ieee_exp >= (-(52 -48)))
	{
		/* ieee subnormal, left shift */
		const int lshift = (52 - 48) + ieee_exp;
		idp->mant = csp->mant << lshift;
		idp->exp  = 0;
	}
	else if(ieee_exp >= -52)
	{
		/* ieee subnormal, right shift */
		const int rshift = (- (52 - 48) - ieee_exp);

		idp->mant = csp->mant >> rshift;

#if 0
		if(csp->mant & (1 << (rshift -1)))
		{
			/* round up */
			idp->mant++;
		}
#endif

		idp->exp  = 0;
	}
	else
	{
		/* smaller than ieee can represent */
		idp->exp = 0;
		idp->mant = 0;
	}
}
#else
#error "ix_double implementation"
#endif

#define ix_double double

static NCX_GET1F(double, schar)
static NCX_GET1F(double, short)
static NCX_GET1F(double, int)
static NCX_GET1F(double, longlong)
static NCX_GET1F(double, uchar)
static NCX_GET1F(double, ushort)
static NCX_GET1F(double, uint)

int
ncx_get_double_ulonglong(const void *xp, unsigned long long *ip)
{
	double xx;
	get_ix_double(xp, &xx);
	*ip = (unsigned long long) xx;
	if(xx > ULONG_LONG_MAX || xx < 0)
		return NC_ERANGE;
	return ENOERR;
}

static int
ncx_get_double_float(const void *xp, float *ip)
{
	double xx;
	get_ix_double(xp, &xx);
	if(xx > FLT_MAX)
	{
		*ip = FLT_MAX;
		return NC_ERANGE;
	}
	if(xx < (-FLT_MAX))
	{
		*ip = (-FLT_MAX);
		return NC_ERANGE;
	}
	*ip = (float) xx;
	return ENOERR;
}

#if X_SIZEOF_DOUBLE != SIZEOF_DOUBLE  || defined(NO_IEEE_FLOAT)
static int
ncx_get_double_double(const void *xp, double *ip)
{
	/* TODO */
	get_ix_double(xp, ip);
	return ENOERR;
}
#endif

static NCX_PUT1F(double, schar)
static NCX_PUT1F(double, uchar)
static NCX_PUT1F(double, short)
static NCX_PUT1F(double, ushort)
static NCX_PUT1F(double, int)
static NCX_PUT1F(double, uint)
static NCX_PUT1F(double, longlong)
static NCX_PUT1F(double, ulonglong)

static int
ncx_put_double_float(void *xp, const float *ip)
{
	double xx = (double) *ip;
	put_ix_double(xp, &xx);
#if 1	/* TODO: figure this out */
	if((double)(*ip) > X_DOUBLE_MAX || (double)(*ip) < X_DOUBLE_MIN)
		return NC_ERANGE;
#endif
	return ENOERR;
}

#if X_SIZEOF_DOUBLE != SIZEOF_DOUBLE  || defined(NO_IEEE_FLOAT)
static int
ncx_put_double_double(void *xp, const double *ip)
{
	put_ix_double(xp, ip);
#ifdef NO_IEEE_FLOAT
	if(*ip > X_DOUBLE_MAX || *ip < X_DOUBLE_MIN)
		return NC_ERANGE;
#endif
	return ENOERR;
}
#endif


/* x_longlong ---------------------------------------------------------------------*/

#if SHORT_MAX == X_LONGLONG_MAX
typedef short ix_longlong;
#define SIZEOF_IX_LONGLONG SIZEOF_SHORT
#define IX_LONGLONG_MAX SHORT_MAX
#elif LONG_LONG_MAX  >= X_LONGLONG_MAX
typedef longlong ix_longlong;
#define SIZEOF_IX_LONGLONG SIZEOF_LONGLONG
#define IX_LONGLONG_MAX LONG_LONG_MAX
#elif LONG_MAX  >= X_LONGLONG_MAX
typedef long ix_longlong;
#define SIZEOF_IX_LONGLONG SIZEOF_LONG
#define IX_LONGLONG_MAX LONG_MAX
#else
#error "ix_longlong implementation"
#endif


static void
get_ix_longlong(const void *xp, ix_longlong *ip)
{
    const uchar *cp = (const uchar *) xp;

    *ip  = ((long long)(*cp++) << 56);
    *ip |= ((long long)(*cp++) << 48);
    *ip |= ((long long)(*cp++) << 40);
    *ip |= ((long long)(*cp++) << 32);
    *ip |= ((long long)(*cp++) << 24);
    *ip |= ((long long)(*cp++) << 16);
    *ip |= ((long long)(*cp++) <<  8);
    *ip |=  (long long)*cp;
}

static void
put_ix_longlong(void *xp, const ix_longlong *ip)
{
    uchar *cp = (uchar *) xp;

    *cp++ = (*ip) >> 56;
    *cp++ = ((*ip) & 0x00ff000000000000LL) >> 48;
    *cp++ = ((*ip) & 0x0000ff0000000000LL) >> 40;
    *cp++ = ((*ip) & 0x000000ff00000000LL) >> 32;
    *cp++ = ((*ip) & 0x00000000ff000000LL) >> 24;
    *cp++ = ((*ip) & 0x0000000000ff0000LL) >> 16;
    *cp++ = ((*ip) & 0x000000000000ff00LL) >>  8;
    *cp   = ((*ip) & 0x00000000000000ffLL);
}

static NCX_GET1I(longlong, schar,     0)
static NCX_GET1I(longlong, short,     1)
static NCX_GET1I(longlong, int,       1)
static NCX_GET1I(longlong, longlong,  1)
static NCX_GET1I(longlong, ushort,    0)
static NCX_GET1I(longlong, uchar,     0)
static NCX_GET1I(longlong, uint,      0)
static NCX_GET1I(longlong, ulonglong, 0)
static NCX_GET1F(longlong, float)
static NCX_GET1F(longlong, double)

static NCX_PUT1I(longlong, schar,     0)
static NCX_PUT1I(longlong, short,     1)
static NCX_PUT1I(longlong, int,       1)
static NCX_PUT1I(longlong, longlong,  1)
static NCX_PUT1I(longlong, ushort,    0)
static NCX_PUT1I(longlong, uchar,     0)
static NCX_PUT1I(longlong, uint,      0)
static NCX_PUT1I(longlong, ulonglong, 0)
static NCX_PUT1F(longlong, float)
static NCX_PUT1F(longlong, double)

/* x_ulonglong --------------------------------------------------------------------*/

#if USHORT_MAX == X_ULONGLONG_MAX
typedef ushort ix_ulonglong;
#define SIZEOF_IX_ULONGLONG SIZEOF_USHORT
#define IX_ULONGLONG_MAX USHORT_MAX
#elif ULONG_LONG_MAX  >= X_ULONGLONG_MAX
typedef ulonglong ix_ulonglong;
#define SIZEOF_IX_ULONGLONG SIZEOF_ULONGLONG
#define IX_ULONGLONG_MAX ULONG_LONG_MAX
#elif ULONG_MAX  >= X_ULONGLONG_MAX
typedef ulong ix_ulonglong;
#define SIZEOF_IX_ULONGLONG SIZEOF_ULONG
#define IX_ULONGLONG_MAX ULONG_MAX
#else
#error "ix_ulonglong implementation"
#endif


static void
get_ix_ulonglong(const void *xp, ix_ulonglong *ip)
{
    const uchar *cp = (const uchar *) xp;

    *ip  = ((unsigned long long)(*cp++) << 56);
    *ip |= ((unsigned long long)(*cp++) << 48);
    *ip |= ((unsigned long long)(*cp++) << 40);
    *ip |= ((unsigned long long)(*cp++) << 32);
    *ip |= ((unsigned long long)(*cp++) << 24);
    *ip |= ((unsigned long long)(*cp++) << 16);
    *ip |= ((unsigned long long)(*cp++) <<  8);
    *ip |=  (unsigned long long)*cp;
}

static void
put_ix_ulonglong(void *xp, const ix_ulonglong *ip)
{
    uchar *cp = (uchar *) xp;

    *cp++ = (*ip) >> 56;
    *cp++ = ((*ip) & 0x00ff000000000000ULL) >> 48;
    *cp++ = ((*ip) & 0x0000ff0000000000ULL) >> 40;
    *cp++ = ((*ip) & 0x000000ff00000000ULL) >> 32;
    *cp++ = ((*ip) & 0x00000000ff000000ULL) >> 24;
    *cp++ = ((*ip) & 0x0000000000ff0000ULL) >> 16;
    *cp++ = ((*ip) & 0x000000000000ff00ULL) >>  8;
    *cp   = ((*ip) & 0x00000000000000ffULL);
}

static NCX_GET1I(ulonglong, schar,     0)
static NCX_GET1I(ulonglong, short,     0)
static NCX_GET1I(ulonglong, int,       0)
static NCX_GET1I(ulonglong, longlong,  0)
static NCX_GET1I(ulonglong, ushort,    1)
static NCX_GET1I(ulonglong, uchar,     1)
static NCX_GET1I(ulonglong, uint,      1)
static NCX_GET1I(ulonglong, ulonglong, 1)
static NCX_GET1F(ulonglong, float)
static NCX_GET1F(ulonglong, double)

static NCX_PUT1I(ulonglong, schar,     0)
static NCX_PUT1I(ulonglong, short,     0)
static NCX_PUT1I(ulonglong, int,       0)
static NCX_PUT1I(ulonglong, longlong,  0)
static NCX_PUT1I(ulonglong, uchar,     1)
static NCX_PUT1I(ulonglong, ushort,    1)
static NCX_PUT1I(ulonglong, uint,      1)
static NCX_PUT1I(ulonglong, ulonglong, 1)
static NCX_PUT1F(ulonglong, float)
static NCX_PUT1F(ulonglong, double)

/* x_size_t */

#if SIZEOF_SIZE_T < X_SIZEOF_SIZE_T
#error "x_size_t implementation"
/* netcdf requires size_t which can hold a values from 0 to 2^32 -1 */
#endif

int
ncx_put_size_t(void **xpp, const size_t *ulp)
{
	/* similar to put_ix_int() */
	uchar *cp = (uchar *) *xpp;
	assert(*ulp <= X_SIZE_MAX);

	*cp++ = (uchar)((*ulp) >> 24);
	*cp++ = (uchar)(((*ulp) & 0x00ff0000) >> 16);
	*cp++ = (uchar)(((*ulp) & 0x0000ff00) >>  8);
	*cp   = (uchar)((*ulp) & 0x000000ff);

	*xpp = (void *)((char *)(*xpp) + X_SIZEOF_SIZE_T);
	return ENOERR;
}

int
ncx_get_size_t(const void **xpp,  size_t *ulp)
{
	/* similar to get_ix_int */
	const uchar *cp = (const uchar *) *xpp;

	*ulp = (unsigned)(*cp++ << 24);
	*ulp |= (*cp++ << 16);
	*ulp |= (*cp++ << 8);
	*ulp |= *cp;

	*xpp = (const void *)((const char *)(*xpp) + X_SIZEOF_SIZE_T);
	return ENOERR;
}

/* x_off_t */

int
ncx_put_off_t(void **xpp, const off_t *lp, size_t sizeof_off_t)
{
	/* similar to put_ix_int() */
	uchar *cp = (uchar *) *xpp;
		/* No negative offsets stored in netcdf */
	if (*lp < 0) {
	  /* Assume this is an overflow of a 32-bit int... */
	  return NC_ERANGE;
	}

	assert(sizeof_off_t == 4 || sizeof_off_t == 8);

	if (sizeof_off_t == 4) {
		*cp++ = (uchar) ((*lp)               >> 24);
		*cp++ = (uchar)(((*lp) & 0x00ff0000) >> 16);
		*cp++ = (uchar)(((*lp) & 0x0000ff00) >>  8);
		*cp   = (uchar)( (*lp) & 0x000000ff);
	} else {
#if SIZEOF_OFF_T == 4
/* Write a 64-bit offset on a system with only a 32-bit offset */
		*cp++ = (uchar)0;
		*cp++ = (uchar)0;
		*cp++ = (uchar)0;
		*cp++ = (uchar)0;

		*cp++ = (uchar)(((*lp) & 0xff000000) >> 24);
		*cp++ = (uchar)(((*lp) & 0x00ff0000) >> 16);
		*cp++ = (uchar)(((*lp) & 0x0000ff00) >>  8);
		*cp   = (uchar)( (*lp) & 0x000000ff);
#else
		*cp++ = (uchar) ((*lp)                          >> 56);
		*cp++ = (uchar)(((*lp) & 0x00ff000000000000ULL) >> 48);
		*cp++ = (uchar)(((*lp) & 0x0000ff0000000000ULL) >> 40);
		*cp++ = (uchar)(((*lp) & 0x000000ff00000000ULL) >> 32);
		*cp++ = (uchar)(((*lp) & 0x00000000ff000000ULL) >> 24);
		*cp++ = (uchar)(((*lp) & 0x0000000000ff0000ULL) >> 16);
		*cp++ = (uchar)(((*lp) & 0x000000000000ff00ULL) >>  8);
		*cp   = (uchar)( (*lp) & 0x00000000000000ffULL);
#endif
	}
	*xpp = (void *)((char *)(*xpp) + sizeof_off_t);
	return ENOERR;
}

int
ncx_get_off_t(const void **xpp, off_t *lp, size_t sizeof_off_t)
{
	/* similar to get_ix_int() */
	const uchar *cp = (const uchar *) *xpp;
	assert(sizeof_off_t == 4 || sizeof_off_t == 8);

 	if (sizeof_off_t == 4) {
		*lp =  (off_t)(*cp++ << 24);
		*lp |= (off_t)(*cp++ << 16);
		*lp |= (off_t)(*cp++ <<  8);
		*lp |= (off_t)*cp;
	} else {
#if SIZEOF_OFF_T == 4
/* Read a 64-bit offset on a system with only a 32-bit offset */
/* If the offset overflows, set an error code and return */
		*lp =  ((off_t)(*cp++) << 24);
		*lp |= ((off_t)(*cp++) << 16);
		*lp |= ((off_t)(*cp++) <<  8);
		*lp |= ((off_t)(*cp++));
/*
 * lp now contains the upper 32-bits of the 64-bit offset.  if lp is
 * not zero, then the dataset is larger than can be represented
 * on this system.  Set an error code and return.
 */
		if (*lp != 0) {
		  return NC_ERANGE;
		}

		*lp  = ((off_t)(*cp++) << 24);
		*lp |= ((off_t)(*cp++) << 16);
		*lp |= ((off_t)(*cp++) <<  8);
		*lp |=  (off_t)*cp;

		if (*lp < 0) {
		  /*
		   * If this fails, then the offset is >2^31, but less
		   * than 2^32 which is not allowed, but is not caught
		   * by the previous check
		   */
		  return NC_ERANGE;
		}
#else
		*lp =  ((off_t)(*cp++) << 56);
		*lp |= ((off_t)(*cp++) << 48);
		*lp |= ((off_t)(*cp++) << 40);
		*lp |= ((off_t)(*cp++) << 32);
		*lp |= ((off_t)(*cp++) << 24);
		*lp |= ((off_t)(*cp++) << 16);
		*lp |= ((off_t)(*cp++) <<  8);
		*lp |=  (off_t)*cp;
#endif
	}
	*xpp = (const void *)((const char *)(*xpp) + sizeof_off_t);
	return ENOERR;
}

/*----< ncx_get_int32() >--------------------------------------------------*/
int
ncx_get_int32(const void **xpp,
              int         *ip)
{
    const uchar *cp = (const uchar *) *xpp;

    /* cannot call swap4b(), as lp is 8-byte */
    *ip  = (*cp++ << 24);
    *ip |= (*cp++ << 16);
    *ip |= (*cp++ <<  8);
    *ip |=  *cp;

    /* advance *xpp 4 bytes */
    *xpp = (void *)((const char *)(*xpp) + 4);

    return NC_NOERR;
}

/*----< ncx_get_int64() >-------------------------------------------------*/
int
ncx_get_int64(const void **xpp,
              long long   *llp)
{
    const uchar *cp = (const uchar *) *xpp;

    /* below is the same as calling swap8b(llp, *xpp) */
    *llp  = ((long long)(*cp++) << 56);
    *llp |= ((long long)(*cp++) << 48);
    *llp |= ((long long)(*cp++) << 40);
    *llp |= ((long long)(*cp++) << 32);
    *llp |= ((long long)(*cp++) << 24);
    *llp |= ((long long)(*cp++) << 16);
    *llp |= ((long long)(*cp++) <<  8);
    *llp |=  (long long)*cp;

    /* advance *xpp 8 bytes */
    *xpp = (void *)((const char *)(*xpp) + 8);

    return NC_NOERR;
}

/*---< ncx_put_int32() >-----------------------------------------------------*/
/* copy the contents of lp (a signed 32-bit integer) to xpp in Big Endian
 * form and advance *xpp 4 bytes
 */
int
ncx_put_int32(void      **xpp,
              const int   ip)
{
#ifdef WORDS_BIGENDIAN
    int *ptr = (int*) (*xpp); /* typecast to 4-byte integer */
    *ptr = ip;
#else
    /* bitwise shifts below are to produce an integer in Big Endian */
    /* cannot call swap4b(), as lp is 8-byte */
    uchar *cp = (uchar *) *xpp;
    *cp++ = (uchar)((ip & 0xff000000) >> 24);
    *cp++ = (uchar)((ip & 0x00ff0000) >> 16);
    *cp++ = (uchar)((ip & 0x0000ff00) >>  8);
    *cp   = (uchar)( ip & 0x000000ff);
#endif
    /* advance *xpp 4 bytes */
    *xpp  = (void *)((char *)(*xpp) + 4);

    return NC_NOERR;
}

/*---< ncx_put_int64() >-----------------------------------------------------*/
/* copy the contents of lp (a signed 64-bit integer) to xpp in Big Endian
 * form and advance *xpp 8 bytes
 */
int
ncx_put_int64(void             **xpp,
              const long long    ip)
{
#ifdef WORDS_BIGENDIAN
    long long *ptr = (long long*) (*xpp); /* typecast to 8-byte integer */
    *ptr = ip;
#else
    uchar *cp = (uchar *) *xpp;
    /* below is the same as calling swap8b(*xpp, &ip) */
    *cp++ = (uchar)((ip & 0xff00000000000000ULL) >> 56);
    *cp++ = (uchar)((ip & 0x00ff000000000000ULL) >> 48);
    *cp++ = (uchar)((ip & 0x0000ff0000000000ULL) >> 40);
    *cp++ = (uchar)((ip & 0x000000ff00000000ULL) >> 32);
    *cp++ = (uchar)((ip & 0x00000000ff000000ULL) >> 24);
    *cp++ = (uchar)((ip & 0x0000000000ff0000ULL) >> 16);
    *cp++ = (uchar)((ip & 0x000000000000ff00ULL) >>  8);
    *cp   = (uchar)( ip & 0x00000000000000ffULL);
#endif
    /* advance *xpp 8 bytes */
    *xpp  = (void *)((char *)(*xpp) + 8);

    return NC_NOERR;
}


/*
 * Aggregate numeric conversion functions.
 */
dnl
define(`GETN_CheckBND', `ifelse(index(`$1',`u'), 0, , `ifelse(index(`$2',`u'), 0, `|| xp[i] < 0', `|| xp[i] < Imin($2)')')')dnl
define(`PUTN_CheckBND', `ifelse(index(`$2',`u'), 0, , `ifelse(index(`$1',`u'), 0, `|| tp[i] < 0', `|| tp[i] < Xmin($1)')')')dnl

dnl
dnl dnl dnl
dnl
dnl NCX_GETN_Byte_Body (body for one byte types on diagonal)
dnl
define(`NCX_GETN_Byte_Body',dnl
`dnl
	(void) memcpy(tp, *xpp, nelems);
	*xpp = (void *)((char *)(*xpp) + nelems);
	return ENOERR;
')dnl
dnl dnl dnl
dnl
dnl NCX_PAD_GETN_Byte_body (body for one byte types on diagonal)
dnl
define(`NCX_PAD_GETN_Byte_Body',dnl
`dnl
	size_t rndup = nelems % X_ALIGN;

	if(rndup)
		rndup = X_ALIGN - rndup;

	(void) memcpy(tp, *xpp, nelems);
	*xpp = (void *)((char *)(*xpp) + nelems + rndup);

	return ENOERR;
')dnl
dnl dnl dnl
dnl
dnl NCX_GETN_CHAR(Type)
dnl
define(`NCX_GETN_CHAR',dnl
`dnl
int
ncx_getn_$1_$2(const void **xpp, size_t nelems, $2 *tp)
{
	int status = ENOERR;
	$1 *xp = ($1 *)(*xpp);

	while(nelems-- != 0)
	{
ifelse(index(`$1',`u'), 0, , `ifelse(index(`$2',`u'), 0, `		if (*xp < 0) status = NC_ERANGE;')')
		*tp++ = *xp++;
	}

	*xpp = (const void *)xp;
	return status;
}
')dnl
dnl dnl dnl
dnl
dnl NCX_PAD_GETN_CHAR(Type)
dnl
define(`NCX_PAD_GETN_CHAR',dnl
`dnl
int
ncx_pad_getn_$1_$2(const void **xpp, size_t nelems, $2 *tp)
{
	int status = ENOERR;
	size_t rndup = nelems % X_ALIGN;
	$1 *xp = ($1 *) *xpp;

	if(rndup)
		rndup = X_ALIGN - rndup;

	while(nelems-- != 0)
	{
ifelse(index(`$1',`u'), 0, , `ifelse(index(`$2',`u'), 0, `		if (*xp < 0) status = NC_ERANGE;')')
		*tp++ = *xp++;
	}

	*xpp = (void *)(xp + rndup);
	return status;
}
')dnl
dnl dnl dnl
dnl
dnl NCX_GETNo(XType, Type) deprecated
dnl
define(`NCX_GETNo',dnl
`dnl
int
ncx_getn_$1_$2(const void **xpp, size_t nelems, $2 *tp)
{
	const char *xp = (const char *) *xpp;
	int status = ENOERR;
	$1 xx;

	for( ; nelems != 0; nelems--, xp += Xsizeof($1), tp++)
	{
		const int lstatus = ncx_get_$1_$1(xp, &xx);
		*tp = ($2)xx;
		if(lstatus != ENOERR)
			status = lstatus;
	}

	*xpp = (const void *)xp;
	return status;
}
')dnl
dnl dnl dnl
dnl
dnl NCX_GETN(XType, Type, condition)
dnl
define(`NCX_GETN',dnl
`dnl
int
ncx_getn_$1_$2(const void **xpp, size_t nelems, $2 *tp)
{
`#'if _SX && Xsizeof($1) == Isizeof($1)

 /* basic algorithm is:
  *   - ensure sane alignment of input data
  *   - copy (conversion happens automatically) input data
  *     to output
  *   - update xpp to point at next unconverted input, and tp to point
  *     at next location for converted output
  */
  long i, j, ni;
  $1 tmp[LOOPCNT];        /* in case input is misaligned */
  $1 *xp;
  int nrange = 0;         /* number of range errors */
  int realign = 0;        /* "do we need to fix input data alignment?" */
  long cxp = (long) *((char**)xpp);

  realign = (cxp & 7) % Isizeof($1);
  /* sjl: manually stripmine so we can limit amount of
   * vector work space reserved to LOOPCNT elements. Also
   * makes vectorisation easy */
  for (j=0; j<nelems && nrange==0; j+=LOOPCNT) {
    ni=Min(nelems-j,LOOPCNT);
    if (realign) {
      memcpy(tmp, *xpp, ni*Isizeof($1));
      xp = tmp;
    } else {
      xp = ($1 *) *xpp;
    }
   /* copy the next block */
#pragma cdir loopcnt=LOOPCNT
#pragma cdir shortloop
    for (i=0; i<ni; i++) {
      tp[i] = ($2) Max( Imin($2), Min(Imax($2), ($2) xp[i]));
     /* test for range errors (not always needed but do it anyway) */
     /* if xpp is unsigned, we need not check if xp[i] < Imin */
     /* if xpp is signed && tp is unsigned, we need check if xp[i] >= 0 */
      nrange += xp[i] > Imax($2) GETN_CheckBND($1, $2);
    }
   /* update xpp and tp */
    if (realign) xp = ($1 *) *xpp;
    xp += ni;
    tp += ni;
    *xpp = (void*)xp;
  }
  return nrange == 0 ? ENOERR : NC_ERANGE;

#else   /* not SX */
	const char *xp = (const char *) *xpp;
	int status = ENOERR;

	for( ; nelems != 0; nelems--, xp += Xsizeof($1), tp++)
	{
		const int lstatus = ncx_get_$1_$2(xp, tp);
		if(lstatus != ENOERR)
			status = lstatus;
	}

	*xpp = (const void *)xp;
	return status;
#  endif
}
')dnl
dnl dnl dnl
dnl
dnl NCX_PAD_GETN_SHORT(xtype ttype)
dnl
define(`NCX_PAD_GETN_SHORT',dnl
`dnl
int
ncx_pad_getn_$1_$2(const void **xpp, size_t nelems, $2 *tp)
{
	const size_t rndup = nelems % 2;

	const char *xp = (const char *) *xpp;
	int status = ENOERR;

	for( ; nelems != 0; nelems--, xp += Xsizeof($1), tp++)
	{
		const int lstatus = ncx_get_$1_$2(xp, tp);
		if(lstatus != ENOERR)
			status = lstatus;
	}

	if(rndup != 0)
		xp += Xsizeof($1);
	*xpp = (void *)xp;
	return status;
}
')dnl
dnl dnl dnl
dnl
dnl NCX_PUTN_Byte_Body(Type) (body for one byte types)
dnl
define(`NCX_PUTN_Byte_Body',dnl
`dnl
	(void) memcpy(*xpp, tp, nelems);
	*xpp = (void *)((char *)(*xpp) + nelems);

	return ENOERR;
')dnl
dnl dnl dnl
dnl
dnl NCX_PAD_PUTN_Byte_Body(Type) (body for one byte types)
dnl
define(`NCX_PAD_PUTN_Byte_Body',dnl
	size_t rndup = nelems % X_ALIGN;

	if(rndup)
		rndup = X_ALIGN - rndup;

	(void) memcpy(*xpp, tp, nelems);
	*xpp = (void *)((char *)(*xpp) + nelems);

	if(rndup)
	{
		(void) memcpy(*xpp, nada, rndup);
		*xpp = (void *)((char *)(*xpp) + rndup);
	}

	return ENOERR;
`dnl
')dnl
dnl dnl dnl
dnl
dnl NCX_PUTN_CHAR(Type)
dnl
define(`NCX_PUTN_CHAR',dnl
`dnl
int
ncx_putn_$1_$2(void **xpp, size_t nelems, const $2 *tp)
{
	int status = ENOERR;
	$1 *xp = ($1 *) *xpp;

	while(nelems-- != 0)
	{
		if(*tp > Xmax($1) ifelse(index(`$2',`u'), 0, , `ifelse(index(`$1',`u'), 0, `|| *tp < 0',`|| *tp < Xmin(schar)')'))
			status = NC_ERANGE;
		*xp++ = ($1) *tp++;
	}

	*xpp = (void *)xp;
	return status;
}
')dnl
dnl dnl dnl
dnl
dnl NCX_PAD_PUTN_CHAR(xtype, ttype)
dnl
define(`NCX_PAD_PUTN_CHAR',dnl
`dnl
int
ncx_pad_putn_$1_$2(void **xpp, size_t nelems, const $2 *tp)
{
	int status = ENOERR;
	size_t rndup = nelems % X_ALIGN;
	$1 *xp = ($1 *) *xpp;

	if(rndup)
		rndup = X_ALIGN - rndup;

	while(nelems-- != 0)
	{
		if(*tp > Xmax($1) ifelse(index(`$2',`u'), 0, , `ifelse(index(`$1',`u'), 0, `|| *tp < 0',`|| *tp < Xmin(schar)')'))
			status = NC_ERANGE;
		*xp++ = ($1) *tp++;
	}


	if(rndup)
	{
		(void) memcpy(xp, nada, rndup);
		xp += rndup;
	}

	*xpp = (void *)xp;
	return status;
}
')dnl
dnl dnl dnl
dnl
dnl NCX_PUTNo(XType, Type) deprecated
dnl
define(`NCX_PUTNo',dnl
`dnl
int
ncx_putn_$1_$2(void **xpp, size_t nelems, const $2 *tp)
{
	char *xp = (char *) *xpp;
	int status = ENOERR;
	$1 xx;

	for( ; nelems != 0; nelems--, xp += Xsizeof($1), tp++)
	{
		xx = ($1) *tp;
		{
		int lstatus = ncx_put_$1_$1(xp, &xx);
		if(lstatus != ENOERR)
			status = lstatus;
		}
	}

	*xpp = (void *)xp;
	return status;
}
')dnl
dnl dnl dnl
dnl
dnl NCX_PUTN(XType, Type, condition)
dnl
define(`NCX_PUTN',dnl
`dnl
int
ncx_putn_$1_$2(void **xpp, size_t nelems, const $2 *tp)
{
`#'if _SX && Xsizeof($1) == Isizeof($1)

 /* basic algorithm is:
  *   - ensure sane alignment of output data
  *   - copy (conversion happens automatically) input data
  *     to output
  *   - update tp to point at next unconverted input, and xpp to point
  *     at next location for converted output
  */
  long i, j, ni;
  $1 tmp[LOOPCNT];        /* in case input is misaligned */
  $1 *xp;
ifelse( $1$2, intfloat,dnl
`dnl
  double d;               /* special case for ncx_putn_int_float */
')dnl
  int nrange = 0;         /* number of range errors */
  int realign = 0;        /* "do we need to fix input data alignment?" */
  long cxp = (long) *((char**)xpp);

  realign = (cxp & 7) % Isizeof($1);
  /* sjl: manually stripmine so we can limit amount of
   * vector work space reserved to LOOPCNT elements. Also
   * makes vectorisation easy */
  for (j=0; j<nelems && nrange==0; j+=LOOPCNT) {
    ni=Min(nelems-j,LOOPCNT);
    if (realign) {
      xp = tmp;
    } else {
      xp = ($1 *) *xpp;
    }
   /* copy the next block */
#pragma cdir loopcnt=LOOPCNT
#pragma cdir shortloop
    for (i=0; i<ni; i++) {
ifelse( $1$2, intfloat,dnl
`dnl
      /* for some reason int to float, for putn, requires a special case */
      d = tp[i];
      xp[i] = ($1) Max( Xmin($1), Min(Xmax($1), ($1) d));
      nrange += tp[i] > Xmax($1) PUTN_CheckBND($1, $2);
',dnl
`dnl
      /* the normal case: */
      xp[i] = ($1) Max( Xmin($1), Min(Xmax($1), ($1) tp[i]));
     /* test for range errors (not always needed but do it anyway) */
     /* if xpp is unsigned && tp is signed, we need check if tp[i] >= 0 */
     /* if tp is unsigned, we need not check if tp[i] < Xmin */
      nrange += tp[i] > Xmax($1) PUTN_CheckBND($1, $2);
')dnl
    }
   /* copy workspace back if necessary */
    if (realign) {
      memcpy(*xpp, tmp, ni*Xsizeof($1));
      xp = ($1 *) *xpp;
    }
   /* update xpp and tp */
    xp += ni;
    tp += ni;
    *xpp = (void*)xp;
  }
  return nrange == 0 ? ENOERR : NC_ERANGE;

#else   /* not SX */

	char *xp = (char *) *xpp;
	int status = ENOERR;

	for( ; nelems != 0; nelems--, xp += Xsizeof($1), tp++)
	{
		int lstatus = ncx_put_$1_$2(xp, tp);
		if(lstatus != ENOERR)
			status = lstatus;
	}

	*xpp = (void *)xp;
	return status;
#endif
}
')dnl
dnl dnl dnl
dnl
dnl NCX_PAD_PUTN_SHORT(xtype, ttype)
dnl
define(`NCX_PAD_PUTN_SHORT',dnl
`dnl
int
ncx_pad_putn_$1_$2(void **xpp, size_t nelems, const $2 *tp)
{
	const size_t rndup = nelems % 2;

	char *xp = (char *) *xpp;
	int status = ENOERR;

	for( ; nelems != 0; nelems--, xp += Xsizeof($1), tp++)
	{
		int lstatus = ncx_put_$1_$2(xp, tp);
		if(lstatus != ENOERR)
			status = lstatus;
	}

	if(rndup != 0)
	{
		(void) memcpy(xp, nada, Xsizeof($1));
		xp += Xsizeof($1);
	}

	*xpp = (void *)xp;
	return status;
}
')dnl

dnl dnl dnl
dnl
dnl Declare & define routines
dnl
dnl dnl dnl

/* schar ---------------------------------------------------------------------*/

dnl NCX_GETN_CHAR(schar, schar)
int
ncx_getn_schar_schar(const void **xpp, size_t nelems, schar *tp)
{
	NCX_GETN_Byte_Body
}
dnl NCX_GETN_CHAR(schar, uchar)
int
ncx_getn_schar_uchar(const void **xpp, size_t nelems, uchar *tp)
{
	NCX_GETN_Byte_Body
}
NCX_GETN_CHAR(schar, short)
NCX_GETN_CHAR(schar, int)
NCX_GETN_CHAR(schar, float)
NCX_GETN_CHAR(schar, double)
NCX_GETN_CHAR(schar, longlong)
NCX_GETN_CHAR(schar, ushort)
NCX_GETN_CHAR(schar, uint)
NCX_GETN_CHAR(schar, ulonglong)

dnl NCX_PAD_GETN_CHAR(schar, schar)
int
ncx_pad_getn_schar_schar(const void **xpp, size_t nelems, schar *tp)
{
	NCX_PAD_GETN_Byte_Body
}
dnl NCX_PAD_GETN_CHAR(schar, uchar)
int
ncx_pad_getn_schar_uchar(const void **xpp, size_t nelems, uchar *tp)
{
	NCX_PAD_GETN_Byte_Body
}
NCX_PAD_GETN_CHAR(schar, short)
NCX_PAD_GETN_CHAR(schar, int)
NCX_PAD_GETN_CHAR(schar, float)
NCX_PAD_GETN_CHAR(schar, double)
NCX_PAD_GETN_CHAR(schar, longlong)
NCX_PAD_GETN_CHAR(schar, ushort)
NCX_PAD_GETN_CHAR(schar, uint)
NCX_PAD_GETN_CHAR(schar, ulonglong)

dnl NCX_PUTN_CHAR(schar, schar)
int
ncx_putn_schar_schar(void **xpp, size_t nelems, const schar *tp)
{
	NCX_PUTN_Byte_Body
}
dnl NCX_PUTN_CHAR(schar, uchar)
int
ncx_putn_schar_uchar(void **xpp, size_t nelems, const uchar *tp)
{
	NCX_PUTN_Byte_Body
}
NCX_PUTN_CHAR(schar, short)
NCX_PUTN_CHAR(schar, int)
NCX_PUTN_CHAR(schar, float)
NCX_PUTN_CHAR(schar, double)
NCX_PUTN_CHAR(schar, longlong)
NCX_PUTN_CHAR(schar, ushort)
NCX_PUTN_CHAR(schar, uint)
NCX_PUTN_CHAR(schar, ulonglong)

dnl NCX_PAD_PUTN_CHAR(schar, schar)
int
ncx_pad_putn_schar_schar(void **xpp, size_t nelems, const schar *tp)
{
	NCX_PAD_PUTN_Byte_Body
}
dnl NCX_PAD_PUTN_CHAR(schar, uchar)
int
ncx_pad_putn_schar_uchar(void **xpp, size_t nelems, const uchar *tp)
{
	NCX_PAD_PUTN_Byte_Body
}
NCX_PAD_PUTN_CHAR(schar, short)
NCX_PAD_PUTN_CHAR(schar, int)
NCX_PAD_PUTN_CHAR(schar, float)
NCX_PAD_PUTN_CHAR(schar, double)
NCX_PAD_PUTN_CHAR(schar, longlong)
NCX_PAD_PUTN_CHAR(schar, ushort)
NCX_PAD_PUTN_CHAR(schar, uint)
NCX_PAD_PUTN_CHAR(schar, ulonglong)


/* uchar ---------------------------------------------------------------------*/
dnl
dnl NCX_GETN_CHAR(uchar, schar)
int
ncx_getn_uchar_schar(const void **xpp, size_t nelems, schar *tp)
{
	NCX_GETN_Byte_Body
}
dnl NCX_GETN_CHAR(uchar, uchar)
int
ncx_getn_uchar_uchar(const void **xpp, size_t nelems, uchar *tp)
{
	NCX_GETN_Byte_Body
}
NCX_GETN_CHAR(uchar, short)
NCX_GETN_CHAR(uchar, int)
NCX_GETN_CHAR(uchar, float)
NCX_GETN_CHAR(uchar, double)
NCX_GETN_CHAR(uchar, longlong)
NCX_GETN_CHAR(uchar, ushort)
NCX_GETN_CHAR(uchar, uint)
NCX_GETN_CHAR(uchar, ulonglong)

dnl NCX_PAD_GETN_CHAR(uchar, schar)
int
ncx_pad_getn_uchar_schar(const void **xpp, size_t nelems, schar *tp)
{
	NCX_PAD_GETN_Byte_Body
}
dnl NCX_PAD_GETN_CHAR(uchar, uchar)
int
ncx_pad_getn_uchar_uchar(const void **xpp, size_t nelems, uchar *tp)
{
	NCX_PAD_GETN_Byte_Body
}
NCX_PAD_GETN_CHAR(uchar, short)
NCX_PAD_GETN_CHAR(uchar, int)
NCX_PAD_GETN_CHAR(uchar, float)
NCX_PAD_GETN_CHAR(uchar, double)
NCX_PAD_GETN_CHAR(uchar, longlong)
NCX_PAD_GETN_CHAR(uchar, ushort)
NCX_PAD_GETN_CHAR(uchar, uint)
NCX_PAD_GETN_CHAR(uchar, ulonglong)

dnl NCX_PUTN_CHAR(uchar, schar)
int
ncx_putn_uchar_schar(void **xpp, size_t nelems, const schar *tp)
{
	NCX_PUTN_Byte_Body
}
dnl NCX_PUTN_CHAR(uchar, uchar)
int
ncx_putn_uchar_uchar(void **xpp, size_t nelems, const uchar *tp)
{
	NCX_PUTN_Byte_Body
}
NCX_PUTN_CHAR(uchar, short)
NCX_PUTN_CHAR(uchar, int)
NCX_PUTN_CHAR(uchar, float)
NCX_PUTN_CHAR(uchar, double)
NCX_PUTN_CHAR(uchar, longlong)
NCX_PUTN_CHAR(uchar, ushort)
NCX_PUTN_CHAR(uchar, uint)
NCX_PUTN_CHAR(uchar, ulonglong)

dnl NCX_PAD_PUTN_UCHAR(uchar, schar)
int
ncx_pad_putn_uchar_schar(void **xpp, size_t nelems, const schar *tp)
{
	NCX_PAD_PUTN_Byte_Body
}
dnl NCX_PAD_PUTN_UCHAR(uchar, uchar)
int
ncx_pad_putn_uchar_uchar(void **xpp, size_t nelems, const uchar *tp)
{
	NCX_PAD_PUTN_Byte_Body
}
NCX_PAD_PUTN_CHAR(uchar, short)
NCX_PAD_PUTN_CHAR(uchar, int)
NCX_PAD_PUTN_CHAR(uchar, float)
NCX_PAD_PUTN_CHAR(uchar, double)
NCX_PAD_PUTN_CHAR(uchar, longlong)
NCX_PAD_PUTN_CHAR(uchar, ushort)
NCX_PAD_PUTN_CHAR(uchar, uint)
NCX_PAD_PUTN_CHAR(uchar, ulonglong)

/* short ---------------------------------------------------------------------*/

#if X_SIZEOF_SHORT == SIZEOF_SHORT
/* optimized version */
int
ncx_getn_short_short(const void **xpp, size_t nelems, short *tp)
{
#ifdef WORDS_BIGENDIAN
	(void) memcpy(tp, *xpp, nelems * sizeof(short));
# else
	swapn2b(tp, *xpp, nelems);
# endif
	*xpp = (const void *)((const char *)(*xpp) + nelems * X_SIZEOF_SHORT);
	return ENOERR;
}
#else
NCX_GETN(short, short)
#endif
NCX_GETN(short, schar)
NCX_GETN(short, int)
NCX_GETN(short, float)
NCX_GETN(short, double)
NCX_GETN(short, longlong)
NCX_GETN(short, uchar)
NCX_GETN(short, ushort)
NCX_GETN(short, uint)
NCX_GETN(short, ulonglong)

NCX_PAD_GETN_SHORT(short, schar)
NCX_PAD_GETN_SHORT(short, uchar)
NCX_PAD_GETN_SHORT(short, short)
NCX_PAD_GETN_SHORT(short, int)
NCX_PAD_GETN_SHORT(short, float)
NCX_PAD_GETN_SHORT(short, double)
NCX_PAD_GETN_SHORT(short, uint)
NCX_PAD_GETN_SHORT(short, longlong)
NCX_PAD_GETN_SHORT(short, ulonglong)
NCX_PAD_GETN_SHORT(short, ushort)

#if X_SIZEOF_SHORT == SIZEOF_SHORT
/* optimized version */
int
ncx_putn_short_short(void **xpp, size_t nelems, const short *tp)
{
#ifdef WORDS_BIGENDIAN
	(void) memcpy(*xpp, tp, nelems * X_SIZEOF_SHORT);
# else
	swapn2b(*xpp, tp, nelems);
# endif
	*xpp = (void *)((char *)(*xpp) + nelems * X_SIZEOF_SHORT);
	return ENOERR;
}
#else
NCX_PUTN(short, short)
#endif
NCX_PUTN(short, schar)
NCX_PUTN(short, int)
NCX_PUTN(short, float)
NCX_PUTN(short, double)
NCX_PUTN(short, longlong)
NCX_PUTN(short, uchar)
NCX_PUTN(short, uint)
NCX_PUTN(short, ulonglong)
NCX_PUTN(short, ushort)

NCX_PAD_PUTN_SHORT(short, schar)
NCX_PAD_PUTN_SHORT(short, uchar)
NCX_PAD_PUTN_SHORT(short, short)
NCX_PAD_PUTN_SHORT(short, int)
NCX_PAD_PUTN_SHORT(short, float)
NCX_PAD_PUTN_SHORT(short, double)
NCX_PAD_PUTN_SHORT(short, uint)
NCX_PAD_PUTN_SHORT(short, longlong)
NCX_PAD_PUTN_SHORT(short, ulonglong)
NCX_PAD_PUTN_SHORT(short, ushort)


/* ushort --------------------------------------------------------------------*/

#if X_SIZEOF_USHORT == SIZEOF_USHORT
/* optimized version */
int
ncx_getn_ushort_ushort(const void **xpp, size_t nelems, unsigned short *tp)
{
#ifdef WORDS_BIGENDIAN
	(void) memcpy(tp, *xpp, nelems * sizeof(unsigned short));
# else
	swapn2b(tp, *xpp, nelems);
# endif
	*xpp = (const void *)((const char *)(*xpp) + nelems * X_SIZEOF_USHORT);
	return ENOERR;
}
#else
NCX_GETN(ushort, ushort)
#endif
NCX_GETN(ushort, schar)
NCX_GETN(ushort, short)
NCX_GETN(ushort, int)
NCX_GETN(ushort, float)
NCX_GETN(ushort, double)
NCX_GETN(ushort, longlong)
NCX_GETN(ushort, uchar)
NCX_GETN(ushort, uint)
NCX_GETN(ushort, ulonglong)

NCX_PAD_GETN_SHORT(ushort, schar)
NCX_PAD_GETN_SHORT(ushort, uchar)
NCX_PAD_GETN_SHORT(ushort, short)
NCX_PAD_GETN_SHORT(ushort, ushort)
NCX_PAD_GETN_SHORT(ushort, int)
NCX_PAD_GETN_SHORT(ushort, uint)
NCX_PAD_GETN_SHORT(ushort, float)
NCX_PAD_GETN_SHORT(ushort, double)
NCX_PAD_GETN_SHORT(ushort, longlong)
NCX_PAD_GETN_SHORT(ushort, ulonglong)

#if X_SIZEOF_USHORT == SIZEOF_USHORT
/* optimized version */
int
ncx_putn_ushort_ushort(void **xpp, size_t nelems, const unsigned short *tp)
{
#ifdef WORDS_BIGENDIAN
	(void) memcpy(*xpp, tp, nelems * X_SIZEOF_USHORT);
# else
	swapn2b(*xpp, tp, nelems);
# endif
	*xpp = (void *)((char *)(*xpp) + nelems * X_SIZEOF_USHORT);
	return ENOERR;
}
#else
NCX_PUTN(ushort, ushort)
#endif
NCX_PUTN(ushort, schar)
NCX_PUTN(ushort, short)
NCX_PUTN(ushort, int)
NCX_PUTN(ushort, float)
NCX_PUTN(ushort, double)
NCX_PUTN(ushort, longlong)
NCX_PUTN(ushort, uchar)
NCX_PUTN(ushort, uint)
NCX_PUTN(ushort, ulonglong)

NCX_PAD_PUTN_SHORT(ushort, schar)
NCX_PAD_PUTN_SHORT(ushort, uchar)
NCX_PAD_PUTN_SHORT(ushort, short)
NCX_PAD_PUTN_SHORT(ushort, int)
NCX_PAD_PUTN_SHORT(ushort, float)
NCX_PAD_PUTN_SHORT(ushort, double)
NCX_PAD_PUTN_SHORT(ushort, uint)
NCX_PAD_PUTN_SHORT(ushort, longlong)
NCX_PAD_PUTN_SHORT(ushort, ulonglong)
NCX_PAD_PUTN_SHORT(ushort, ushort)


/* int -----------------------------------------------------------------------*/

#if X_SIZEOF_INT == SIZEOF_INT
/* optimized version */
int
ncx_getn_int_int(const void **xpp, size_t nelems, int *tp)
{
#ifdef WORDS_BIGENDIAN
	(void) memcpy(tp, *xpp, nelems * sizeof(int));
# else
	swapn4b(tp, *xpp, nelems);
# endif
	*xpp = (const void *)((const char *)(*xpp) + nelems * X_SIZEOF_INT);
	return ENOERR;
}
#else
NCX_GETN(int, int)
#endif
NCX_GETN(int, schar)
NCX_GETN(int, short)
NCX_GETN(int, float)
NCX_GETN(int, double)
NCX_GETN(int, longlong)
NCX_GETN(int, uchar)
NCX_GETN(int, ushort)
NCX_GETN(int, uint)
NCX_GETN(int, ulonglong)

#if X_SIZEOF_INT == SIZEOF_INT
/* optimized version */
int
ncx_putn_int_int(void **xpp, size_t nelems, const int *tp)
{
#ifdef WORDS_BIGENDIAN
	(void) memcpy(*xpp, tp, nelems * X_SIZEOF_INT);
# else
	swapn4b(*xpp, tp, nelems);
# endif
	*xpp = (void *)((char *)(*xpp) + nelems * X_SIZEOF_INT);
	return ENOERR;
}
#else
NCX_PUTN(int, int)
#endif
NCX_PUTN(int, schar)
NCX_PUTN(int, short)
NCX_PUTN(int, float)
NCX_PUTN(int, double)
NCX_PUTN(int, longlong)
NCX_PUTN(int, uchar)
NCX_PUTN(int, ushort)
NCX_PUTN(int, uint)
NCX_PUTN(int, ulonglong)

/* uint ----------------------------------------------------------------------*/

#if X_SIZEOF_UINT == SIZEOF_UINT
/* optimized version */
int
ncx_getn_uint_uint(const void **xpp, size_t nelems, unsigned int *tp)
{
#ifdef WORDS_BIGENDIAN
	(void) memcpy(tp, *xpp, nelems * sizeof(uint));
# else
	swapn4b(tp, *xpp, nelems);
# endif
	*xpp = (const void *)((const char *)(*xpp) + nelems * X_SIZEOF_UINT);
	return ENOERR;
}
#else
NCX_GETN(uint, uint)
#endif
NCX_GETN(uint, schar)
NCX_GETN(uint, short)
NCX_GETN(uint, int)
NCX_GETN(uint, float)
NCX_GETN(uint, double)
NCX_GETN(uint, longlong)
NCX_GETN(uint, uchar)
NCX_GETN(uint, ushort)
NCX_GETN(uint, ulonglong)

#if X_SIZEOF_UINT == SIZEOF_UINT
/* optimized version */
int
ncx_putn_uint_uint(void **xpp, size_t nelems, const unsigned int *tp)
{
#ifdef WORDS_BIGENDIAN
	(void) memcpy(*xpp, tp, nelems * X_SIZEOF_UINT);
# else
	swapn4b(*xpp, tp, nelems);
# endif
	*xpp = (void *)((char *)(*xpp) + nelems * X_SIZEOF_UINT);
	return ENOERR;
}
#else
NCX_PUTN(uint, uint)
#endif
NCX_PUTN(uint, schar)
NCX_PUTN(uint, short)
NCX_PUTN(uint, int)
NCX_PUTN(uint, float)
NCX_PUTN(uint, double)
NCX_PUTN(uint, longlong)
NCX_PUTN(uint, uchar)
NCX_PUTN(uint, ushort)
NCX_PUTN(uint, ulonglong)


/* float ---------------------------------------------------------------------*/

#if X_SIZEOF_FLOAT == SIZEOF_FLOAT && !defined(NO_IEEE_FLOAT)
/* optimized version */
int
ncx_getn_float_float(const void **xpp, size_t nelems, float *tp)
{
#ifdef WORDS_BIGENDIAN
	(void) memcpy(tp, *xpp, nelems * sizeof(float));
# else
	swapn4b(tp, *xpp, nelems);
# endif
	*xpp = (const void *)((const char *)(*xpp) + nelems * X_SIZEOF_FLOAT);
	return ENOERR;
}
#elif vax
int
ncx_getn_float_float(const void **xpp, size_t nfloats, float *ip)
{
	float *const end = ip + nfloats;

	while(ip < end)
	{
GET_VAX_DFLOAT_Body(`(*xpp)')

		ip++;
		*xpp = (char *)(*xpp) + X_SIZEOF_FLOAT;
	}
	return ENOERR;
}
#else
int
ncx_getn_float_float(const void **xpp, size_t nelems, float *tp)
{
	const char *xp = *xpp;
	int status = ENOERR;

	for( ; nelems != 0; nelems--, xp += X_SIZEOF_FLOAT, tp++)
	{
		const int lstatus = ncx_get_float_float(xp, tp);
		if(lstatus != ENOERR)
			status = lstatus;
	}

	*xpp = (const void *)xp;
	return status;
}

#endif
NCX_GETN(float, schar)
NCX_GETN(float, short)
NCX_GETN(float, int)
NCX_GETN(float, double)
NCX_GETN(float, longlong)
NCX_GETN(float, ushort)
NCX_GETN(float, uchar)
NCX_GETN(float, uint)
NCX_GETN(float, ulonglong)

#if X_SIZEOF_FLOAT == SIZEOF_FLOAT && !defined(NO_IEEE_FLOAT)
/* optimized version */
int
ncx_putn_float_float(void **xpp, size_t nelems, const float *tp)
{
#ifdef WORDS_BIGENDIAN
	(void) memcpy(*xpp, tp, nelems * X_SIZEOF_FLOAT);
# else
	swapn4b(*xpp, tp, nelems);
# endif
	*xpp = (void *)((char *)(*xpp) + nelems * X_SIZEOF_FLOAT);
	return ENOERR;
}
#elif vax
int
ncx_putn_float_float(void **xpp, size_t nfloats, const float *ip)
{
	const float *const end = ip + nfloats;

	while(ip < end)
	{
PUT_VAX_DFLOAT_Body(`(*xpp)')

		ip++;
		*xpp = (char *)(*xpp) + X_SIZEOF_FLOAT;
	}
	return ENOERR;
}
#else
int
ncx_putn_float_float(void **xpp, size_t nelems, const float *tp)
{
	char *xp = *xpp;
	int status = ENOERR;

	for( ; nelems != 0; nelems--, xp += X_SIZEOF_FLOAT, tp++)
	{
		int lstatus = ncx_put_float_float(xp, tp);
		if(lstatus != ENOERR)
			status = lstatus;
	}

	*xpp = (void *)xp;
	return status;
}
#endif
NCX_PUTN(float, schar)
NCX_PUTN(float, short)
NCX_PUTN(float, int)
NCX_PUTN(float, double)
NCX_PUTN(float, longlong)
NCX_PUTN(float, uchar)
NCX_PUTN(float, ushort)
NCX_PUTN(float, uint)
NCX_PUTN(float, ulonglong)

/* double --------------------------------------------------------------------*/

#if X_SIZEOF_DOUBLE == SIZEOF_DOUBLE && !defined(NO_IEEE_FLOAT)
/* optimized version */
int
ncx_getn_double_double(const void **xpp, size_t nelems, double *tp)
{
#ifdef WORDS_BIGENDIAN
	(void) memcpy(tp, *xpp, nelems * sizeof(double));
# else
	swapn8b(tp, *xpp, nelems);
# endif
	*xpp = (const void *)((const char *)(*xpp) + nelems * X_SIZEOF_DOUBLE);
	return ENOERR;
}
#elif vax
int
ncx_getn_double_double(const void **xpp, size_t ndoubles, double *ip)
{
	double *const end = ip + ndoubles;

	while(ip < end)
	{
GET_VAX_DDOUBLE_Body(`(*xpp)')
		ip++;
		*xpp = (char *)(*xpp) + X_SIZEOF_DOUBLE;
	}
	return ENOERR;
}
	/* vax */
#else
int
ncx_getn_double_double(const void **xpp, size_t nelems, double *tp)
{
	const char *xp = *xpp;
	int status = ENOERR;

	for( ; nelems != 0; nelems--, xp += X_SIZEOF_DOUBLE, tp++)
	{
		const int lstatus = ncx_get_double_double(xp, tp);
		if(lstatus != ENOERR)
			status = lstatus;
	}

	*xpp = (const void *)xp;
	return status;
}
#endif
NCX_GETN(double, schar)
NCX_GETN(double, short)
NCX_GETN(double, int)
NCX_GETN(double, float)
NCX_GETN(double, longlong)
NCX_GETN(double, uchar)
NCX_GETN(double, ushort)
NCX_GETN(double, uint)
NCX_GETN(double, ulonglong)

#if X_SIZEOF_DOUBLE == SIZEOF_DOUBLE && !defined(NO_IEEE_FLOAT)
/* optimized version */
int
ncx_putn_double_double(void **xpp, size_t nelems, const double *tp)
{
#ifdef WORDS_BIGENDIAN
	(void) memcpy(*xpp, tp, nelems * X_SIZEOF_DOUBLE);
# else
	swapn8b(*xpp, tp, nelems);
# endif
	*xpp = (void *)((char *)(*xpp) + nelems * X_SIZEOF_DOUBLE);
	return ENOERR;
}
#elif vax
int
ncx_putn_double_double(void **xpp, size_t ndoubles, const double *ip)
{
	const double *const end = ip + ndoubles;

	while(ip < end)
	{
PUT_VAX_DDOUBLE_Body(`(*xpp)')
		ip++;
		*xpp = (char *)(*xpp) + X_SIZEOF_DOUBLE;
	}
	return ENOERR;
}
	/* vax */
#else
int
ncx_putn_double_double(void **xpp, size_t nelems, const double *tp)
{
	char *xp = *xpp;
	int status = ENOERR;

	for( ; nelems != 0; nelems--, xp += X_SIZEOF_DOUBLE, tp++)
	{
		int lstatus = ncx_put_double_double(xp, tp);
		if(lstatus != ENOERR)
			status = lstatus;
	}

	*xpp = (void *)xp;
	return status;
}
#endif
NCX_PUTN(double, schar)
NCX_PUTN(double, short)
NCX_PUTN(double, int)
NCX_PUTN(double, float)
NCX_PUTN(double, longlong)
NCX_PUTN(double, uchar)
NCX_PUTN(double, ushort)
NCX_PUTN(double, uint)
NCX_PUTN(double, ulonglong)


/* longlong -----------------------------------------------------------------------*/

#if X_SIZEOF_LONGLONG == SIZEOF_LONGLONG
/* optimized version */
int
ncx_getn_longlong_longlong(const void **xpp, size_t nelems, long long *tp)
{
#ifdef WORDS_BIGENDIAN
	(void) memcpy(tp, *xpp, nelems * sizeof(long long));
# else
	swapn8b(tp, *xpp, nelems);
# endif
	*xpp = (const void *)((const char *)(*xpp) + nelems * X_SIZEOF_LONGLONG);
	return ENOERR;
}
#else
NCX_GETN(longlong, longlong)
#endif
NCX_GETN(longlong, schar)
NCX_GETN(longlong, short)
NCX_GETN(longlong, int)
NCX_GETN(longlong, float)
NCX_GETN(longlong, double)
NCX_GETN(longlong, uchar)
NCX_GETN(longlong, ushort)
NCX_GETN(longlong, uint)
NCX_GETN(longlong, ulonglong)

#if X_SIZEOF_LONGLONG == SIZEOF_LONGLONG
/* optimized version */
int
ncx_putn_longlong_longlong(void **xpp, size_t nelems, const long long *tp)
{
#ifdef WORDS_BIGENDIAN
	(void) memcpy(*xpp, tp, nelems * X_SIZEOF_LONGLONG);
# else
	swapn8b(*xpp, tp, nelems);
# endif
	*xpp = (void *)((char *)(*xpp) + nelems * X_SIZEOF_LONGLONG);
	return ENOERR;
}
#else
NCX_PUTN(longlong, longlong)
#endif
NCX_PUTN(longlong, schar)
NCX_PUTN(longlong, short)
NCX_PUTN(longlong, int)
NCX_PUTN(longlong, float)
NCX_PUTN(longlong, double)
NCX_PUTN(longlong, uchar)
NCX_PUTN(longlong, ushort)
NCX_PUTN(longlong, uint)
NCX_PUTN(longlong, ulonglong)

/* ulonglong ----------------------------------------------------------------------*/

#if X_SIZEOF_ULONGLONG == SIZEOF_ULONGLONG
/* optimized version */
int
ncx_getn_ulonglong_ulonglong(const void **xpp, size_t nelems, unsigned long long *tp)
{
#ifdef WORDS_BIGENDIAN
	(void) memcpy(tp, *xpp, nelems * sizeof(unsigned long long));
# else
	swapn8b(tp, *xpp, nelems);
# endif
	*xpp = (const void *)((const char *)(*xpp) + nelems * X_SIZEOF_ULONGLONG);
	return ENOERR;
}
#else
NCX_GETN(ulonglong, ulonglong)
#endif
NCX_GETN(ulonglong, schar)
NCX_GETN(ulonglong, short)
NCX_GETN(ulonglong, int)
NCX_GETN(ulonglong, float)
NCX_GETN(ulonglong, double)
NCX_GETN(ulonglong, longlong)
NCX_GETN(ulonglong, uchar)
NCX_GETN(ulonglong, ushort)
NCX_GETN(ulonglong, uint)

#if X_SIZEOF_ULONGLONG == SIZEOF_ULONGLONG
/* optimized version */
int
ncx_putn_ulonglong_ulonglong(void **xpp, size_t nelems, const unsigned long long *tp)
{
#ifdef WORDS_BIGENDIAN
	(void) memcpy(*xpp, tp, nelems * X_SIZEOF_ULONGLONG);
# else
	swapn8b(*xpp, tp, nelems);
# endif
	*xpp = (void *)((char *)(*xpp) + nelems * X_SIZEOF_ULONGLONG);
	return ENOERR;
}
#else
NCX_PUTN(ulonglong, ulonglong)
#endif
NCX_PUTN(ulonglong, schar)
NCX_PUTN(ulonglong, short)
NCX_PUTN(ulonglong, int)
NCX_PUTN(ulonglong, float)
NCX_PUTN(ulonglong, double)
NCX_PUTN(ulonglong, longlong)
NCX_PUTN(ulonglong, uchar)
NCX_PUTN(ulonglong, ushort)
NCX_PUTN(ulonglong, uint)


/*
 * Other aggregate conversion functions.
 */

/* text */

int
ncx_getn_text(const void **xpp, size_t nelems, char *tp)
{
NCX_GETN_Byte_Body
}

int
ncx_pad_getn_text(const void **xpp, size_t nelems, char *tp)
{
NCX_PAD_GETN_Byte_Body
}

int
ncx_putn_text(void **xpp, size_t nelems, const char *tp)
{
NCX_PUTN_Byte_Body
}

int
ncx_pad_putn_text(void **xpp, size_t nelems, const char *tp)
{
NCX_PAD_PUTN_Byte_Body
}


/* opaque */

int
ncx_getn_void(const void **xpp, size_t nelems, void *tp)
{
NCX_GETN_Byte_Body
}

int
ncx_pad_getn_void(const void **xpp, size_t nelems, void *tp)
{
NCX_PAD_GETN_Byte_Body
}

int
ncx_putn_void(void **xpp, size_t nelems, const void *tp)
{
NCX_PUTN_Byte_Body
}

int
ncx_pad_putn_void(void **xpp, size_t nelems, const void *tp)
{
NCX_PAD_PUTN_Byte_Body
}