dnl Process this m4 file to produce 'C' language file.
dnl
dnl This file is supposed to be the same as PnetCDF's ncx.m4
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 (C) 2014, Northwestern University and Argonne National Laboratory
 *  See COPYRIGHT notice in top-level directory.
 */
/* $Id: ncx.m4 2601 2016-11-07 04:54:42Z wkliao $ */

#ifdef __GNUC__
#pragma GCC diagnostic ignored "-Wunused-parameter"
#endif

dnl
dnl If "ERANGE_FILL" is defined, the data elements that cause NC_ERANGE will
dnl be filled with the NC default fill values.
dnl

define(`SKIP_LOOP', `
#ifdef ERANGE_FILL
            $1++; $2++; continue;
#endif')

dnl
dnl The command-line m4 macro "PNETCDF" is to differentiate PnetCDF and netCDF
dnl in terms of function prefix names (ncmpi_ vs. nc_), integer data types
dnl (MPI_Offset vs. size_t), and function name substrings for external data
dnl types.
dnl

ifdef(`PNETCDF',`
`#'if HAVE_CONFIG_H
`#'include <ncconfig.h>
`#'endif',`
`#'if HAVE_CONFIG_H
`#'include <config.h>
`#'endif')

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <limits.h>

ifdef(`PNETCDF',`
`#'include "ncx.h"
`#'include "macro.h"',`
`#'pragma GCC diagnostic ignored "-Wdeprecated"
`#'include "ncx.h"
`#'include "nc3dispatch.h"')

define(`IntType',  `ifdef(`PNETCDF', `MPI_Offset', `size_t')')dnl
define(`APIPrefix',`ifdef(`PNETCDF', `ncmpi', `nc')')dnl
define(`NC_TYPE',  `ifdef(`PNETCDF', `ifelse(
`$1', `schar',  `NC_BYTE',dnl
`$1', `uchar',  `NC_UBYTE',dnl
`$1', `short',  `NC_SHORT',dnl
`$1', `ushort', `NC_USHORT',dnl
`$1', `int',    `NC_INT',dnl
`$1', `uint',   `NC_UINT',dnl
`$1', `float',  `NC_FLOAT',dnl
`$1', `double', `NC_DOUBLE',dnl
`$1', `int64',  `NC_INT64',dnl
`$1', `uint64', `NC_UINT64')',dnl
`ifelse(
`$1', `int64', `longlong',dnl
`$1', `uint64', `ulonglong',dnl
`$1')')')dnl

ifdef(`PNETCDF',,`define(`DEBUG_RETURN_ERROR',`return $1;')')
ifdef(`PNETCDF',,`define(`DEBUG_ASSIGN_ERROR',`$1 = $2;')')

#ifdef HAVE_INTTYPES_H
#include <inttypes.h> /* uint16_t, uint32_t, uint64_t */
#elif defined(HAVE_STDINT_H)
#include <stdint.h>   /* uint16_t, uint32_t, uint64_t */
#endif

dnl
dnl *fillp is the fill value in internal representation
dnl
define(`FillValue', `
#ifdef ERANGE_FILL
            ifelse(
`$1', `schar',     `if (fillp != NULL) memcpy($2, fillp, 1);',dnl
`$1', `uchar',     `if (fillp != NULL) memcpy($2, fillp, 1);',dnl
`$1', `short',     `if (fillp != NULL) memcpy($2, fillp, 2);',dnl
`$1', `ushort',    `if (fillp != NULL) memcpy($2, fillp, 2);',dnl
`$1', `int',       `if (fillp != NULL) memcpy($2, fillp, 4);',dnl
`$1', `uint',      `if (fillp != NULL) memcpy($2, fillp, 4);',dnl
`$1', `long',      `if (fillp != NULL) memcpy($2, fillp, SIZEOF_LONG);', dnl
`$1', `ulong',     `if (fillp != NULL) memcpy($2, fillp, SIZEOF_ULONG);',dnl
`$1', `float',     `if (fillp != NULL) memcpy($2, fillp, 4);',dnl
`$1', `double',    `if (fillp != NULL) memcpy($2, fillp, 8);',dnl
`$1', `longlong',  `if (fillp != NULL) memcpy($2, fillp, 8);',dnl
`$1', `int64',     `if (fillp != NULL) memcpy($2, fillp, 8);',dnl
`$1', `ulonglong', `if (fillp != NULL) memcpy($2, fillp, 8);',dnl
`$1', `uint64',    `if (fillp != NULL) memcpy($2, fillp, 8);')
#endif')dnl

dnl
dnl
define(`FillDefaultValue', `ifelse(
`$1', `schar',     `NC_FILL_BYTE',
`$1', `uchar',     `NC_FILL_UBYTE',
`$1', `short',     `NC_FILL_SHORT',
`$1', `ushort',    `NC_FILL_USHORT',
`$1', `int',       `NC_FILL_INT',
`$1', `uint',      `NC_FILL_UINT',
`$1', `long',      `NC_FILL_INT',
`$1', `ulong',     `NC_FILL_UINT',
`$1', `float',     `NC_FILL_FLOAT',
`$1', `double',    `NC_FILL_DOUBLE',
`$1', `longlong',  `NC_FILL_INT64',
`$1', `int64',     `NC_FILL_INT64',
`$1', `ulonglong', `NC_FILL_UINT64',
`$1', `uint64',    `NC_FILL_UINT64')')dnl

/*
 * The only error code returned from subroutines in this file is NC_ERANGE,
 * if errors are detected.
 */

/*
 * An external data representation interface.
 */

/* 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_UCHAR
#ifdef  SIZEOF_UNSIGNED_CHAR
#define SIZEOF_UCHAR SIZEOF_UNSIGNED_CHAR
#else
#error "unknown SIZEOF_UCHAR"
#endif
#endif

#ifndef SIZEOF_USHORT
#ifdef  SIZEOF_UNSIGNED_SHORT_INT
#define SIZEOF_USHORT SIZEOF_UNSIGNED_SHORT_INT
#elif defined(SIZEOF_UNSIGNED_SHORT)
#define SIZEOF_USHORT SIZEOF_UNSIGNED_SHORT
#else
#error "unknown SIZEOF_USHORT"
#endif
#endif

#ifndef SIZEOF_UINT
#ifdef  SIZEOF_UNSIGNED_INT
#define SIZEOF_UINT SIZEOF_UNSIGNED_INT
#else
#error "unknown SIZEOF_UINT"
#endif
#endif

#ifndef SIZEOF_LONGLONG
#ifdef  SIZEOF_LONG_LONG
#define SIZEOF_LONGLONG SIZEOF_LONG_LONG
#else
#error "unknown SIZEOF_LONGLONG"
#endif
#endif

#ifndef SIZEOF_INT64
#ifdef  SIZEOF_LONG_LONG
#define SIZEOF_INT64 SIZEOF_LONG_LONG
#elif defined(SIZEOF_LONGLONG)
#define SIZEOF_INT64 SIZEOF_LONGLONG
#else
#error "unknown SIZEOF_INT64"
#endif
#endif

#ifndef SIZEOF_ULONGLONG
#ifdef  SIZEOF_UNSIGNED_LONG_LONG
#define SIZEOF_ULONGLONG SIZEOF_UNSIGNED_LONG_LONG
#else
#error "unknown SIZEOF_ULONGLONG"
#endif
#endif

#ifndef SIZEOF_UINT64
#ifdef  SIZEOF_UNSIGNED_LONG_LONG
#define SIZEOF_UINT64 SIZEOF_UNSIGNED_LONG_LONG
#elif defined(SIZEOF_ULONGLONG)
#define SIZEOF_UINT64 SIZEOF_ULONGLONG
#else
#error "unknown SIZEOF_UINT64"
#endif
#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 defined(_SX) && _SX != 0 /* 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 BIG ENDIAN.
 * Optimize the swapn?b() and swap?b() routines aggressively.
 */

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

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

#define SWAP8(a) ( (((a) & 0x00000000000000FFULL) << 56) | \
                   (((a) & 0x000000000000FF00ULL) << 40) | \
                   (((a) & 0x0000000000FF0000ULL) << 24) | \
                   (((a) & 0x00000000FF000000ULL) <<  8) | \
                   (((a) & 0x000000FF00000000ULL) >>  8) | \
                   (((a) & 0x0000FF0000000000ULL) >> 24) | \
                   (((a) & 0x00FF000000000000ULL) >> 40) | \
                   (((a) & 0xFF00000000000000ULL) >> 56) )

#if defined(_MSC_VER) && _MSC_VER < 1900
#define inline __inline
#endif

inline static void
swapn2b(void *dst, const void *src, IntType nn)
{
    /* it is OK if dst == src */
    IntType i;
    uint16_t *op = (uint16_t*) dst;
    uint16_t *ip = (uint16_t*) src;
    for (i=0; i<nn; i++) {
        op[i] = ip[i];
        op[i] = (uint16_t)SWAP2(op[i]);
    }
#if 0
	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);
	}
#endif
}

# ifndef vax
inline static void
swap4b(void *dst, const void *src)
{
    /* copy over, make the below swap in-place */
    uint32_t tmp;
    /* use memcpy to avoid type punning */
    memcpy(&tmp, src, sizeof(tmp));
    tmp = SWAP4(tmp);
    memcpy(dst, &tmp, 4);

    /* Codes below will cause "break strict-aliasing rules" in gcc
    uint32_t *op = (uint32_t*)dst;
    *op = *(uint32_t*)src;
    *op = SWAP4(*op);
    */

    /* Below are copied from netCDF-4.
     * See https://bugtracking.unidata.ucar.edu/browse/NCF-338
     * Quote "One issue we are wrestling with is how compilers optimize this
     * code.  For some reason, we are actually needing to add an artificial
     * move to a 4 byte space to get it to work.  I think what is happening is
     * that the optimizer is bit shifting within a double, which is incorrect.
     * The following code actually does work correctly.
     *  This is in Linux land, gcc.
     *
     * However, the above in-place byte-swap does not appear affected by this.
     */
#if 0
    uint32_t *ip = (uint32_t*)src;
    uint32_t tempOut;  /* cannot use pointer when gcc O2 optimizer is used */
    tempOut = SWAP4(*ip);

    *(float *)dst = *(float *)(&tempOut);
#endif

    /* OLD implementation that results in four load and four store CPU
       instructions
    char *op = dst;
    const char *ip = src;
    op[0] = ip[3];
    op[1] = ip[2];
    op[2] = ip[1];
    op[3] = ip[0];
    */

}
# endif /* !vax */

inline static void
swapn4b(void *dst, const void *src, IntType nn)
{
    IntType i;
    uint32_t *op = (uint32_t*) dst;
    uint32_t *ip = (uint32_t*) src;
    for (i=0; i<nn; i++) {
        /* copy over, make the below swap in-place */
        op[i] = ip[i];
        op[i] = SWAP4(op[i]);
    }

#if 0
	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;
	}
#endif
}

# ifndef vax
inline static void
swap8b(void *dst, const void *src)
{
#ifdef FLOAT_WORDS_BIGENDIAN
    /* copy over, make the below swap in-place */
    *(uint64_t*)dst = *(uint64_t*)src;

    uint32_t *op = (uint32_t*)dst;
    *op = SWAP4(*op);
    op = (uint32_t*)((char*)dst+4);
    *op = SWAP4(*op);
#else
    uint64_t tmp;
    /* use memcpy to avoid type punning */
    memcpy(&tmp, src, sizeof(tmp));
    tmp = SWAP8(tmp);
    memcpy(dst, &tmp, 8);

    /* Codes below will cause "break strict-aliasing rules" in gcc
    uint64_t *op = (uint64_t*)dst;
    *op = *(uint64_t*)src;
    *op = SWAP8(*op);
    */
#endif

#if 0
	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
}
# endif /* !vax */

# ifndef vax
inline static void
swapn8b(void *dst, const void *src, IntType nn)
{
#ifdef FLOAT_WORDS_BIGENDIAN
    IntType i;
    uint64_t *dst_p = (uint64_t*) dst;
    uint64_t *src_p = (uint64_t*) src;
    for (i=0; i<nn; i++) {
        /* copy over, make the below swap in-place */
        dst_p[i] = src_p[i];
        uint32_t *op = (uint32_t*)(&dst_p[i]);
        *op = SWAP4(*op);
        op = (uint32_t*)((char*)op+4);
        *op = SWAP4(*op);
    }
#else
    IntType i;
    uint64_t *op = (uint64_t*) dst;
    uint64_t *ip = (uint64_t*) src;
    for (i=0; i<nn; i++) {
        /* copy over, make the below swap in-place */
        op[i] = ip[i];
        op[i] = SWAP8(op[i]);
    }
#endif

#if 0
	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
}
# 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', `(double)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

define(`Cast_Signed2Unsigned',
       `ifelse(index(`$1',`u'), 0,
               `ifelse(index(`$2',`u'), 0, , `(signed)')')')dnl

dnl
dnl For GET APIs boundary check
dnl
define(`GETF_CheckBND',
`if (xx > (double)Upcase($1)_MAX || xx < Dmin($1)) {
#ifdef ERANGE_FILL
            *ip = FillDefaultValue($1);
#endif
            DEBUG_RETURN_ERROR(NC_ERANGE)
        }
	*ip = ($1)xx;')dnl

dnl
dnl For GET APIs boudnary check for when $1 is either 'longlong' or 'ulonglong'
dnl
define(`GETF_CheckBND2',
       `ifelse(index(`$1',`u'), 0,
`if (xx == Upcase($1)_MAX)      *ip = Upcase($1)_MAX;',dnl for unsigned type
`if (xx == Upcase($1)_MAX)      *ip = Upcase($1)_MAX;
	else if (xx == Upcase($1)_MIN) *ip = Upcase($1)_MIN;')
	else if (xx > (double)Upcase($1)_MAX || xx < Dmin($1)) {
#ifdef ERANGE_FILL
            *ip = FillDefaultValue($1);
#endif
            DEBUG_RETURN_ERROR(NC_ERANGE)
        }
	else *ip = ($1)xx;')

/*
 * Primitive numeric conversion functions.
 */

dnl dnl dnl
dnl
dnl NCX_GET1F(xtype, itype) for floating-point types
dnl
define(`NCX_GET1F',dnl
`dnl
static int
APIPrefix`x_get_'NC_TYPE($1)_$2(const void *xp, $2 *ip)
{
	ix_$1 xx = 0;
	get_ix_$1(xp, &xx);
	ifelse(`$1', `float',  `ifelse(`$2',  `longlong', GETF_CheckBND2($2),
	                               `$2', `ulonglong', GETF_CheckBND2($2),
	                               `$2',    `double', `*ip = ($2)xx;',
				                          GETF_CheckBND($2))',
	       `$1', `double', `ifelse(`$2',  `longlong', GETF_CheckBND2($2),
	                               `$2', `ulonglong', GETF_CheckBND2($2),
				                          GETF_CheckBND($2))',
	       `*ip = ($2)xx;')
	return NC_NOERR;
}
')dnl

dnl dnl dnl
dnl
dnl NCX_GET1I(xtype, itype, isComptable) for integral types
dnl
define(`NCX_GET1I',dnl
`dnl
static int
APIPrefix`x_get_'NC_TYPE($1)_$2(const void *xp, $2 *ip)
{
    int err=NC_NOERR;
ifelse(`$3', `1',
``#'if IXsizeof($1) == Isizeof($2) && IXmax($1) == Upcase($2)_MAX
    get_ix_$1(xp, (ix_$1 *)ip);
`#'else
')dnl
    ix_$1 xx = 0;
    get_ix_$1(xp, &xx);

`#'if IXmax($1) > Imax($2)
    if (xx > Imax($2)'`ifelse(index(`$1',`u'), 0, ,
                              index(`$2',`u'), 0, ,
                              ` || xx < Imin($2)')'`) {
#ifdef ERANGE_FILL
        *ip = FillDefaultValue($2);
        DEBUG_RETURN_ERROR(NC_ERANGE)
#else
        DEBUG_ASSIGN_ERROR(err, NC_ERANGE)
#endif
    }'
`#'endif

`ifelse(index(`$1',`u'), 0, , index(`$2',`u'), 0,`dnl
    if (xx < 0) {
#ifdef ERANGE_FILL
        *ip = FillDefaultValue($2);
        DEBUG_RETURN_ERROR(NC_ERANGE)
#else
        DEBUG_ASSIGN_ERROR(err, NC_ERANGE) /* because ip is unsigned */
#endif
    }')'dnl

    *ip = ($2) xx;
`ifelse(`$3', `1', ``#'endif
')dnl
    return err;
}
')dnl

dnl dnl dnl
dnl
dnl NCX_PUT1F(xtype, itype) for floating-point types
dnl
define(`NCX_PUT1F',dnl
`dnl
static int
APIPrefix`x_put_'NC_TYPE($1)_$2(void *xp, const $2 *ip, void *fillp)
{
    int err=NC_NOERR;
    ix_$1 xx = FillDefaultValue($1);

    ifelse(`$2', `double', `if (*ip > Xmax($1) || *ip < DXmin($1)) {
        FillValue($1, &xx)
        DEBUG_ASSIGN_ERROR(err, NC_ERANGE)
    }
#ifdef ERANGE_FILL
    else
#endif',
        `$2', `float',  `if (*ip > (double)Xmax($1) || *ip < FXmin($1)) {
        FillValue($1, &xx)
        DEBUG_ASSIGN_ERROR(err, NC_ERANGE)
    }
#ifdef ERANGE_FILL
    else
#endif')
        xx = (ix_$1)*ip;

    put_ix_$1(xp, &xx);
    return err;
}
')dnl

dnl dnl dnl
dnl
dnl NCX_PUT1I(xtype, itype, isComptable) for integral types
dnl
define(`NCX_PUT1I',dnl
`dnl
static int
APIPrefix`x_put_'NC_TYPE($1)_$2(void *xp, const $2 *ip, void *fillp)
{
    int err=NC_NOERR;
ifelse(`$3', `1',
``#'if IXsizeof($1) == Isizeof($2) && IXmax($1) == Upcase($2)_MAX
    put_ix_$1(xp, (const ix_$1 *)ip);
`#'else
')dnl
    ix_$1 xx = FillDefaultValue($1);

`#'if IXmax($1) < Imax($2)
    if (*ip > IXmax($1)'`ifelse(index(`$1',`u'), 0, ,
                                index(`$2',`u'), 0, ,
                                ` || *ip < Xmin($1)')'`) {
        FillValue($1, &xx)
        DEBUG_ASSIGN_ERROR(err, NC_ERANGE)
    }
#ifdef ERANGE_FILL
    else
#endif
`#'endif
ifelse(index(`$1',`u'), 0, `ifelse(index(`$2',`u'), 0, ,`dnl
    if (*ip < 0) {
        FillValue($1, &xx)
        DEBUG_ASSIGN_ERROR(err, NC_ERANGE) /* because xp is unsigned */
    }
#ifdef ERANGE_FILL
    else
#endif
')')dnl
        xx = (ix_$1)*ip;

    put_ix_$1(xp, &xx);
ifelse(`$3', `1', ``#'endif
')dnl
    return err;
}
')dnl

/* x_schar */
/* x_uchar */

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


/* external NC_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_LONGLONG
#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 = (ix_short)(*cp++ << 8);
#if SIZEOF_IX_SHORT > X_SIZEOF_SHORT
	if (*ip & 0x8000)
	{
		/* extern is negative */
		*ip |= (~(0xffff)); /* N.B. Assumes "twos complement" */
	}
#endif
	*ip = (ix_short)(*ip | *cp);
}

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

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

static int
APIPrefix`x_put_'NC_TYPE(short)_schar(void *xp, const schar *ip, void *fillp)
{
	uchar *cp = (uchar *) xp;
	if (*ip & 0x80)
		*cp++ = 0xff;
	else
		*cp++ = 0;
	*cp = (uchar)*ip;
	return NC_NOERR;
}

static int
APIPrefix`x_put_'NC_TYPE(short)_uchar(void *xp, const uchar *ip, void *fillp)
{
	uchar *cp = (uchar *) xp;
	*cp++ = 0;
	*cp = *ip;
	return NC_NOERR;
}

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

/* external NC_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_ULONGLONG
#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 = (ix_ushort)(*cp++ << 8);
#if SIZEOF_IX_SHORT > X_SIZEOF_SHORT
	if (*ip & 0x8000)
	{
		/* extern is negative */
		*ip |= (~(0xffff)); /* N.B. Assumes "twos complement" */
	}
#endif
	*ip = (ix_ushort)(*ip | *cp);
}

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

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

static int
APIPrefix`x_put_'NC_TYPE(ushort)_schar(void *xp, const schar *ip, void *fillp)
{
    int err=NC_NOERR;
    uchar *cp;
    if (*ip < 0) {
#ifdef ERANGE_FILL
        if (fillp != NULL) memcpy(xp, fillp, 2);
#ifndef WORDS_BIGENDIAN
        swapn2b(xp, xp, 1);
#endif
        DEBUG_RETURN_ERROR(NC_ERANGE)
#else
        DEBUG_ASSIGN_ERROR(err, NC_ERANGE)
#endif
    }

    cp = (uchar *) xp;
    if (*ip & 0x80)
        *cp++ = 0xff;
    else
        *cp++ = 0;
    *cp = (uchar)*ip;

    return err;
}

static int
APIPrefix`x_put_'NC_TYPE(ushort)_uchar(void *xp, const uchar *ip, void *fillp)
{
	uchar *cp = (uchar *) xp;
	*cp++ = 0;
	*cp = *ip;
	return NC_NOERR;
}

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

/* external NC_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;

#if INT_MAX  >= X_INT_MAX
	*ip = (ix_int)((unsigned)(*cp++) << 24);
#else
	*ip = *cp++ << 24;
#endif
#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++ = (uchar)( (*ip) >> 24);
	*cp++ = (uchar)(((*ip) & 0x00ff0000) >> 16);
	*cp++ = (uchar)(((*ip) & 0x0000ff00) >>  8);
	*cp   = (uchar)( (*ip) & 0x000000ff);
}

#if X_SIZEOF_INT != SIZEOF_INT
NCX_GET1I(int, int,       1)
#endif
NCX_GET1I(int, schar,     0)
NCX_GET1I(int, short,     1)
NCX_GET1I(int, long,      1)
NCX_GET1I(int, longlong,  1)
NCX_GET1I(int, ushort,    0)
NCX_GET1I(int, uchar,     0)
NCX_GET1I(int, uint,      0)
NCX_GET1I(int, ulonglong, 0)
NCX_GET1F(int, float)
NCX_GET1F(int, double)

static int
APIPrefix`x_put_'NC_TYPE(int)_schar(void *xp, const schar *ip, void *fillp)
{
	uchar *cp = (uchar *) xp;
	if (*ip & 0x80)
	{
		*cp++ = 0xff;
		*cp++ = 0xff;
		*cp++ = 0xff;
	}
	else
	{
		*cp++ = 0x00;
		*cp++ = 0x00;
		*cp++ = 0x00;
	}
	*cp = (uchar)*ip;
	return NC_NOERR;
}

static int
APIPrefix`x_put_'NC_TYPE(int)_uchar(void *xp, const uchar *ip, void *fillp)
{
	uchar *cp = (uchar *) xp;
	*cp++ = 0x00;
	*cp++ = 0x00;
	*cp++ = 0x00;
	*cp   = *ip;
	return NC_NOERR;
}

#if X_SIZEOF_INT != SIZEOF_INT
NCX_PUT1I(int, int,       1)
#endif
NCX_PUT1I(int, short,     1)
NCX_PUT1I(int, long,      1)
NCX_PUT1I(int, longlong,  1)
NCX_PUT1I(int, ushort,    0)
NCX_PUT1I(int, uint,      0)
NCX_PUT1I(int, ulonglong, 0)
NCX_PUT1F(int, float)
NCX_PUT1F(int, double)


/* external NC_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 = (ix_uint)(*cp++ << 24);
	*ip = (ix_uint)(*ip | (ix_uint)(*cp++ << 16));
	*ip = (ix_uint)(*ip | (ix_uint)(*cp++ << 8));
	*ip = (ix_uint)(*ip | *cp);
}

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

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

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

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

static int
APIPrefix`x_put_'NC_TYPE(uint)_schar(void *xp, const schar *ip, void *fillp)
{
    uchar *cp;
    if (*ip < 0) {
#ifdef ERANGE_FILL
        if (fillp != NULL) memcpy(xp, fillp, 4);
#ifndef WORDS_BIGENDIAN
        swapn4b(xp, xp, 1);
#endif
#endif
        DEBUG_RETURN_ERROR(NC_ERANGE)
    }

    cp = (uchar *) xp;
    *cp++ = 0x00;
    *cp++ = 0x00;
    *cp++ = 0x00;
    *cp = (uchar)*ip;

    return NC_NOERR;
}

static int
APIPrefix`x_put_'NC_TYPE(uint)_uchar(void *xp, const uchar *ip, void *fillp)
{
	uchar *cp = (uchar *) xp;
	*cp++ = 0x00;
	*cp++ = 0x00;
	*cp++ = 0x00;
	*cp   = *ip;
	return NC_NOERR;
}

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

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


/* external NC_FLOAT --------------------------------------------------------*/

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

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

inline 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 defined(vax) && vax != 0

/* 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
APIPrefix`x_get_'NC_TYPE(float)_float(const void *xp, float *ip, void *fillp)
{
	/* TODO */
	get_ix_float(xp, ip);
	return NC_NOERR;
}
#endif

#define ix_float float

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

#if X_SIZEOF_FLOAT != SIZEOF_FLOAT || defined(NO_IEEE_FLOAT)
static int
APIPrefix`x_put_'NC_TYPE(float)_float(void *xp, const float *ip, void *fillp)
{
    int err=NC_NOERR;
    float *_ip=ip;
#ifdef NO_IEEE_FLOAT
#ifdef ERANGE_FILL
    float tmp;
#endif
    if (*ip > X_FLOAT_MAX || *ip < X_FLOAT_MIN) {
        FillValue(float, &tmp)
#ifdef ERANGE_FILL
        _ip = &tmp;
#endif
        DEBUG_ASSIGN_ERROR(err, NC_ERANGE)
    }
#endif
    put_ix_float(xp, _ip);
    return err;
}
#endif

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


/* external NC_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 defined(vax) && vax != 0

/* 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

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

static int
APIPrefix`x_get_'NC_TYPE(double)_float(const void *xp, float *ip)
{
    double xx = 0.0;
    get_ix_double(xp, &xx);
    if (xx > FLT_MAX) {
#ifdef ERANGE_FILL
        *ip = NC_FILL_FLOAT;
#else
        *ip = FLT_MAX;
#endif
        DEBUG_RETURN_ERROR(NC_ERANGE)
    }
    if (xx < (-FLT_MAX)) {
#ifdef ERANGE_FILL
        *ip = NC_FILL_FLOAT;
#else
        *ip = (-FLT_MAX);
#endif
        DEBUG_RETURN_ERROR(NC_ERANGE)
    }
    *ip = (float) xx;
    return NC_NOERR;
}

#if X_SIZEOF_DOUBLE != SIZEOF_DOUBLE  || defined(NO_IEEE_FLOAT)
static int
APIPrefix`x_get_'NC_TYPE(double)_double(const void *xp, double *ip, void *fillp)
{
	/* TODO */
	get_ix_double(xp, ip);
	return NC_NOERR;
}
#endif

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

static int
APIPrefix`x_put_'NC_TYPE(double)_float(void *xp, const float *ip, void *fillp)
{
    int err=NC_NOERR;
    double xx = FillDefaultValue(double);
#if 1	/* TODO: figure this out (if condition below will never be true)*/
    if ((double)(*ip) > X_DOUBLE_MAX || (double)(*ip) < X_DOUBLE_MIN) {
        FillValue(double, &xx)
        DEBUG_ASSIGN_ERROR(err, NC_ERANGE)
    }
#ifdef ERANGE_FILL
    else
#endif
#endif
        xx = (double) *ip;

    put_ix_double(xp, &xx);
    return err;
}

#if X_SIZEOF_DOUBLE != SIZEOF_DOUBLE  || defined(NO_IEEE_FLOAT)
static int
APIPrefix`x_put_'NC_TYPE(double)_double(void *xp, const double *ip, void *fillp)
{
    int err=NC_NOERR;
    double *_ip = ip;
#ifdef NO_IEEE_FLOAT
#ifdef ERANGE_FILL
    double tmp=NC_FILL_DOUBLE;
#endif
    if (*ip > X_DOUBLE_MAX || *ip < X_DOUBLE_MIN) {
        FillValue(double, &tmp)
#ifdef ERANGE_FILL
        _ip = &tmp;
#endif
        DEBUG_ASSIGN_ERROR(err, NC_ERANGE)
    }
#endif
    put_ix_double(xp, _ip);
    return err;
}
#endif


/* external NC_INT64 --------------------------------------------------------*/

#if SHORT_MAX == X_INT64_MAX
typedef short ix_int64;
#define SIZEOF_IX_INT64 SIZEOF_SHORT
#define IX_INT64_MAX SHORT_MAX
#elif LONG_LONG_MAX  >= X_INT64_MAX
typedef longlong ix_int64;
#define SIZEOF_IX_INT64 SIZEOF_LONGLONG
#define IX_INT64_MAX LONG_LONG_MAX
#elif LONG_MAX  >= X_INT64_MAX
typedef long ix_int64;
#define SIZEOF_IX_INT64 SIZEOF_LONG
#define IX_INT64_MAX LONG_MAX
#else
#error "ix_int64 implementation"
#endif


static void
get_ix_int64(const void *xp, ix_int64 *ip)
{
    const uchar *cp = (const uchar *) xp;

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

static void
put_ix_int64(void *xp, const ix_int64 *ip)
{
    uchar *cp = (uchar *) xp;

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

#if X_SIZEOF_INT64 != SIZEOF_LONGLONG
NCX_GET1I(int64, longlong,  1)
#endif
NCX_GET1I(int64, schar,     0)
NCX_GET1I(int64, short,     1)
NCX_GET1I(int64, int,       1)
NCX_GET1I(int64, long,      1)
NCX_GET1I(int64, ushort,    0)
NCX_GET1I(int64, uchar,     0)
NCX_GET1I(int64, uint,      0)
NCX_GET1I(int64, ulonglong, 0)
NCX_GET1F(int64, float)
NCX_GET1F(int64, double)

#if X_SIZEOF_INT64 != SIZEOF_LONGLONG
NCX_PUT1I(int64, longlong,  1)
#endif
NCX_PUT1I(int64, schar,     0)
NCX_PUT1I(int64, short,     1)
NCX_PUT1I(int64, int,       1)
NCX_PUT1I(int64, long,      1)
NCX_PUT1I(int64, ushort,    0)
NCX_PUT1I(int64, uchar,     0)
NCX_PUT1I(int64, uint,      0)
NCX_PUT1I(int64, ulonglong, 0)
NCX_PUT1F(int64, float)
NCX_PUT1F(int64, double)


/* external NC_UINT64 -------------------------------------------------------*/

#if USHORT_MAX == X_UINT64_MAX
typedef ushort ix_uint64;
#define SIZEOF_IX_UINT64 SIZEOF_USHORT
#define IX_UINT64_MAX USHORT_MAX
#elif ULONG_LONG_MAX  >= X_UINT64_MAX
typedef ulonglong ix_uint64;
#define SIZEOF_IX_UINT64 SIZEOF_ULONGLONG
#define IX_UINT64_MAX ULONG_LONG_MAX
#elif ULONG_MAX  >= X_UINT64_MAX
typedef ulong ix_uint64;
#define SIZEOF_IX_UINT64 SIZEOF_ULONG
#define IX_UINT64_MAX ULONG_MAX
#else
#error "ix_uint64 implementation"
#endif


static void
get_ix_uint64(const void *xp, ix_uint64 *ip)
{
    const uchar *cp = (const uchar *) xp;

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

static void
put_ix_uint64(void *xp, const ix_uint64 *ip)
{
    uchar *cp = (uchar *) xp;

    *cp++ = (uchar)((*ip) >> 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);
}

#if X_SIZEOF_UINT64 != SIZEOF_ULONGLONG
NCX_GET1I(uint64, ulonglong, 1)
#endif
NCX_GET1I(uint64, schar,     0)
NCX_GET1I(uint64, short,     0)
NCX_GET1I(uint64, int,       0)
NCX_GET1I(uint64, long,      0)
NCX_GET1I(uint64, longlong,  0)
NCX_GET1I(uint64, ushort,    1)
NCX_GET1I(uint64, uchar,     1)
NCX_GET1I(uint64, uint,      1)
NCX_GET1F(uint64, float)
NCX_GET1F(uint64, double)

#if X_SIZEOF_UINT64 != SIZEOF_ULONGLONG
NCX_PUT1I(uint64, ulonglong, 1)
#endif
NCX_PUT1I(uint64, schar,     0)
NCX_PUT1I(uint64, short,     0)
NCX_PUT1I(uint64, int,       0)
NCX_PUT1I(uint64, long,      0)
NCX_PUT1I(uint64, longlong,  0)
NCX_PUT1I(uint64, uchar,     1)
NCX_PUT1I(uint64, ushort,    1)
NCX_PUT1I(uint64, uint,      1)
NCX_PUT1F(uint64, float)
NCX_PUT1F(uint64, 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
APIPrefix`x_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 NC_NOERR;
}

int
APIPrefix`x_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 NC_NOERR;
}

/* x_off_t */

int
APIPrefix`x_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... */
	  DEBUG_RETURN_ERROR(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) & 0x00ff000000000000LL) >> 48);
		*cp++ = (uchar)(((*lp) & 0x0000ff0000000000LL) >> 40);
		*cp++ = (uchar)(((*lp) & 0x000000ff00000000LL) >> 32);
		*cp++ = (uchar)(((*lp) & 0x00000000ff000000LL) >> 24);
		*cp++ = (uchar)(((*lp) & 0x0000000000ff0000LL) >> 16);
		*cp++ = (uchar)(((*lp) & 0x000000000000ff00LL) >>  8);
		*cp   = (uchar)( (*lp) & 0x00000000000000ffLL);
#endif
	}
	*xpp = (void *)((char *)(*xpp) + sizeof_off_t);
	return NC_NOERR;
}

int
APIPrefix`x_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) {
		  DEBUG_RETURN_ERROR(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
		   */
		  DEBUG_RETURN_ERROR(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 NC_NOERR;
}

/*----< APIPrefix`x_get_uint32'() >------------------------------------------*/
int
APIPrefix`x_get_uint32'(const void **xpp, uint *ip)
{
#ifdef WORDS_BIGENDIAN
    /* use memcpy instead of assignment to avoid BUS_ADRALN alignment error on
     * some system, such as HPUX */
    (void) memcpy(ip, *xpp, SIZEOF_UINT);
#else
    const uchar *cp = (const uchar *) *xpp;

    *ip = (uint)(*cp++ << 24);
    *ip = (uint)(*ip | (uint)(*cp++ << 16));
    *ip = (uint)(*ip | (uint)(*cp++ <<  8));
    *ip = (uint)(*ip | *cp);
#endif
    /* advance *xpp 4 bytes */
    *xpp = (void *)((const char *)(*xpp) + 4);

    return NC_NOERR;
}

/*----< APIPrefix`x_get_uint64'() >------------------------------------------*/
int
APIPrefix`x_get_uint64'(const void **xpp, unsigned long long *ullp)
{
#ifdef WORDS_BIGENDIAN
    /* use memcpy instead of assignment to avoid BUS_ADRALN alignment error on
     * some system, such as HPUX */
    (void) memcpy(ullp, *xpp, SIZEOF_UINT64);
#else
    const uchar *cp = (const uchar *) *xpp;

    /* below is the same as calling swap8b(ullp, *xpp) */
    *ullp = (unsigned long long)(*cp++) << 56;
    *ullp = (unsigned long long)(*ullp | (unsigned long long)(*cp++) << 48);
    *ullp = (unsigned long long)(*ullp | (unsigned long long)(*cp++) << 40);
    *ullp = (unsigned long long)(*ullp | (unsigned long long)(*cp++) << 32);
    *ullp = (unsigned long long)(*ullp | (unsigned long long)(*cp++) << 24);
    *ullp = (unsigned long long)(*ullp | (unsigned long long)(*cp++) << 16);
    *ullp = (unsigned long long)(*ullp | (unsigned long long)(*cp++) <<  8);
    *ullp = (unsigned long long)(*ullp | (unsigned long long)(*cp));
#endif
    /* advance *xpp 8 bytes */
    *xpp = (void *)((const char *)(*xpp) + 8);

    return NC_NOERR;
}

/*---< APIPrefix`x_put_uint32'() >-------------------------------------------*/
/* copy the contents of ip (an unsigned 32-bit integer) to xpp in Big Endian
 * form and advance *xpp 4 bytes
 */
int
APIPrefix`x_put_uint32'(void **xpp, const unsigned int ip)
{
#ifdef WORDS_BIGENDIAN
    /* use memcpy instead of assignment to avoid BUS_ADRALN alignment error on
     * some system, such as HPUX */
    (void) memcpy(*xpp, &ip, X_SIZEOF_UINT);
#else
    /* bitwise shifts below are to produce an integer in Big Endian */
    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;
}

/*---< APIPrefix`x_put_uint64'() >-------------------------------------------*/
/* copy the contents of ip (an unsigned 64-bit integer) to xpp in Big Endian
 * form and advance *xpp 8 bytes
 */
int
APIPrefix`x_put_uint64'(void **xpp, const unsigned long long ip)
{
#ifdef WORDS_BIGENDIAN
    /* use memcpy instead of assignment to avoid BUS_ADRALN alignment error on
     * some system, such as HPUX */
    (void) memcpy(*xpp, &ip, X_SIZEOF_UINT64);
#else
    uchar *cp = (uchar *) *xpp;
    /* below is the same as calling swap8b(*xpp, &ip) */
    *cp++ = (uchar) (ip                         >> 56);
    *cp++ = (uchar)((ip & 0x00ff000000000000LL) >> 48);
    *cp++ = (uchar)((ip & 0x0000ff0000000000LL) >> 40);
    *cp++ = (uchar)((ip & 0x000000ff00000000LL) >> 32);
    *cp++ = (uchar)((ip & 0x00000000ff000000LL) >> 24);
    *cp++ = (uchar)((ip & 0x0000000000ff0000LL) >> 16);
    *cp++ = (uchar)((ip & 0x000000000000ff00LL) >>  8);
    *cp   = (uchar) (ip & 0x00000000000000ffLL);
#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, , index(`$2',`u'), 0, `|| xp[i] < 0', `|| xp[i] < Imin($2)')')dnl
define(`PUTN_CheckBND', `ifelse(index(`$2',`u'), 0, , 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, (size_t)nelems);
	*xpp = (void *)((char *)(*xpp) + nelems);
	return NC_NOERR;
')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
	IntType rndup = nelems % X_ALIGN;

	if (rndup)
		rndup = X_ALIGN - rndup;

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

	return NC_NOERR;
')dnl
dnl dnl dnl
dnl
dnl NCX_GETN_BYTE(xtype, itype)
dnl
define(`NCX_GETN_BYTE',dnl
`dnl
int
APIPrefix`x_getn_'NC_TYPE($1)_$2(const void **xpp, IntType nelems, $2 *tp)
{
    int status = NC_NOERR;
    $1 *xp = ($1 *)(*xpp);

    while (nelems-- != 0) {
        ifelse(index(`$1',`u'), 0, ,
               index(`$2',`u'), 0, `
        if (*xp < 0) {
#ifdef ERANGE_FILL
            *tp = FillDefaultValue($2);
#endif
            DEBUG_ASSIGN_ERROR(status, NC_ERANGE) /* because tp is unsigned */
            SKIP_LOOP(xp, tp)
        }')dnl

        *tp++ = ($2) Cast_Signed2Unsigned($2,$1) (*xp++);  /* type cast from $1 to $2 */
    }

    *xpp = (const void *)xp;
    return status;
}
')dnl
dnl dnl dnl
dnl
dnl NCX_PAD_GETN_BYTE(xtype, itype)
dnl
define(`NCX_PAD_GETN_BYTE',dnl
`dnl
int
APIPrefix`x_pad_getn_'NC_TYPE($1)_$2(const void **xpp, IntType nelems, $2 *tp)
{
    int status = NC_NOERR;
    IntType rndup = nelems % X_ALIGN;
    $1 *xp = ($1 *) *xpp;

    if (rndup)
        rndup = X_ALIGN - rndup;

    while (nelems-- != 0) {
        ifelse(index(`$1',`u'), 0, ,
               index(`$2',`u'), 0, `
        if (*xp < 0) {
#ifdef ERANGE_FILL
            *tp = FillDefaultValue($2);
#endif
            DEBUG_ASSIGN_ERROR(status, NC_ERANGE) /* because tp is unsigned */
            SKIP_LOOP(xp, tp)
        }')dnl

        *tp++ = ($2) Cast_Signed2Unsigned($2,$1) (*xp++);  /* type cast from $1 to $2 */
    }

    *xpp = (void *)(xp + rndup);
    return status;
}
')dnl
dnl dnl dnl
dnl
dnl NCX_GETN(xtype, itype)
dnl
define(`NCX_GETN',dnl
`dnl
int
APIPrefix`x_getn_'NC_TYPE($1)_$2(const void **xpp, IntType nelems, $2 *tp)
{
`#'if defined(_SX) && _SX != 0 && 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, (size_t)(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 ? NC_NOERR : NC_ERANGE;

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

	for( ; nelems != 0; nelems--, xp += Xsizeof($1), tp++)
	{
		const int lstatus = APIPrefix`x_get_'NC_TYPE($1)_$2(xp, tp);
		if (status == NC_NOERR) /* report the first encountered error */
			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
APIPrefix`x_pad_getn_'NC_TYPE($1)_$2(const void **xpp, IntType nelems, $2 *tp)
{
	const IntType rndup = nelems % X_SIZEOF_SHORT;

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

	for( ; nelems != 0; nelems--, xp += Xsizeof($1), tp++)
	{
		const int lstatus = APIPrefix`x_get_'NC_TYPE($1)_$2(xp, tp);
		if (status == NC_NOERR) /* report the first encountered error */
			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, (size_t)nelems);
	*xpp = (void *)((char *)(*xpp) + nelems);

	return NC_NOERR;
')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
	IntType rndup = nelems % X_ALIGN;

	if (rndup)
		rndup = X_ALIGN - rndup;

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

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

	return NC_NOERR;
`dnl
')dnl
dnl dnl dnl
dnl
dnl NCX_PUTN_BYTE(xtype, itype)
dnl
define(`NCX_PUTN_BYTE',dnl
`dnl
int
APIPrefix`x_putn_'NC_TYPE($1)_$2(void **xpp, IntType nelems, const $2 *tp, void *fillp)
{
    int status = NC_NOERR;
    $1 *xp = ($1 *) *xpp;

    while (nelems-- != 0) {
        if (*tp > ($2)Xmax($1) ifelse(index(`$2',`u'), 0, , index(`$1',`u'), 0, `|| *tp < 0',`|| *tp < Xmin(schar)')) {
            FillValue($1, xp)
            DEBUG_ASSIGN_ERROR(status, NC_ERANGE)
            SKIP_LOOP(xp, tp)
        }
        *xp++ = ($1) Cast_Signed2Unsigned($1,$2) *tp++; /* type cast from $2 to $1 */
    }

    *xpp = (void *)xp;
    return status;
}
')dnl
dnl dnl dnl
dnl
dnl NCX_PAD_PUTN_BYTE(xtype, ttype)
dnl
define(`NCX_PAD_PUTN_BYTE',dnl
`dnl
int
APIPrefix`x_pad_putn_'NC_TYPE($1)_$2(void **xpp, IntType nelems, const $2 *tp, void *fillp)
{
    int status = NC_NOERR;
    IntType rndup = nelems % X_ALIGN;
    $1 *xp = ($1 *) *xpp;

    if (rndup) rndup = X_ALIGN - rndup;

    while (nelems-- != 0) {
        if (*tp > ($2)Xmax($1) ifelse(index(`$2',`u'), 0, , index(`$1',`u'), 0, `|| *tp < 0',`|| *tp < Xmin(schar)')) {
            FillValue($1, xp)
            DEBUG_ASSIGN_ERROR(status, NC_ERANGE)
            SKIP_LOOP(xp, tp)
        }
        *xp++ = ($1) Cast_Signed2Unsigned($1,$2) *tp++; /* type cast from $2 to $1 */
    }


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

    *xpp = (void *)xp;
    return status;
}
')dnl
dnl dnl dnl
dnl
dnl NCX_PUTN(xtype, itype)
dnl
define(`NCX_PUTN',dnl
`dnl
int
APIPrefix`x_putn_'NC_TYPE($1)_$2(void **xpp, IntType nelems, const $2 *tp, void *fillp)
{
`#'if defined(_SX) && _SX != 0 && 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 APIPrefix`x_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, (size_t)*ni*Xsizeof($1));
      xp = ($1 *) *xpp;
    }
   /* update xpp and tp */
    xp += ni;
    tp += ni;
    *xpp = (void*)xp;
  }
  return nrange == 0 ? NC_NOERR : NC_ERANGE;

#else   /* not SX */

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

	for( ; nelems != 0; nelems--, xp += Xsizeof($1), tp++)
	{
		int lstatus = APIPrefix`x_put_'NC_TYPE($1)_$2(xp, tp, fillp);
		if (status == NC_NOERR) /* report the first encountered error */
			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
APIPrefix`x_pad_putn_'NC_TYPE($1)_$2(void **xpp, IntType nelems, const $2 *tp, void *fillp)
{
	const IntType rndup = nelems % X_SIZEOF_SHORT;

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

	for( ; nelems != 0; nelems--, xp += Xsizeof($1), tp++)
	{
		int lstatus = APIPrefix`x_put_'NC_TYPE($1)_$2(xp, tp, fillp);
		if (status == NC_NOERR) /* report the first encountered error */
			status = lstatus;
	}

	if (rndup != 0)
	{
		(void) memcpy(xp, nada, (size_t)(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_BYTE(schar, schar)
int
APIPrefix`x_getn_'NC_TYPE(schar)_schar(const void **xpp, IntType nelems, schar *tp)
{
	NCX_GETN_Byte_Body
}
NCX_GETN_BYTE(schar, uchar)
NCX_GETN_BYTE(schar, short)
NCX_GETN_BYTE(schar, int)
NCX_GETN_BYTE(schar, long)
NCX_GETN_BYTE(schar, float)
NCX_GETN_BYTE(schar, double)
NCX_GETN_BYTE(schar, longlong)
NCX_GETN_BYTE(schar, ushort)
NCX_GETN_BYTE(schar, uint)
NCX_GETN_BYTE(schar, ulonglong)

dnl NCX_PAD_GETN_BYTE(schar, schar)
int
APIPrefix`x_pad_getn_'NC_TYPE(schar)_schar(const void **xpp, IntType nelems, schar *tp)
{
	NCX_PAD_GETN_Byte_Body
}
NCX_PAD_GETN_BYTE(schar, uchar)
NCX_PAD_GETN_BYTE(schar, short)
NCX_PAD_GETN_BYTE(schar, int)
NCX_PAD_GETN_BYTE(schar, long)
NCX_PAD_GETN_BYTE(schar, float)
NCX_PAD_GETN_BYTE(schar, double)
NCX_PAD_GETN_BYTE(schar, longlong)
NCX_PAD_GETN_BYTE(schar, ushort)
NCX_PAD_GETN_BYTE(schar, uint)
NCX_PAD_GETN_BYTE(schar, ulonglong)

dnl NCX_PUTN_BYTE(schar, schar)
int
APIPrefix`x_putn_'NC_TYPE(schar)_schar(void **xpp, IntType nelems, const schar *tp, void *fillp)
{
	NCX_PUTN_Byte_Body
}
NCX_PUTN_BYTE(schar, uchar)
NCX_PUTN_BYTE(schar, short)
NCX_PUTN_BYTE(schar, int)
NCX_PUTN_BYTE(schar, long)
NCX_PUTN_BYTE(schar, float)
NCX_PUTN_BYTE(schar, double)
NCX_PUTN_BYTE(schar, longlong)
NCX_PUTN_BYTE(schar, ushort)
NCX_PUTN_BYTE(schar, uint)
NCX_PUTN_BYTE(schar, ulonglong)

dnl NCX_PAD_PUTN_BYTE(schar, schar)
int
APIPrefix`x_pad_putn_'NC_TYPE(schar)_schar(void **xpp, IntType nelems, const schar *tp, void *fillp)
{
	NCX_PAD_PUTN_Byte_Body
}
NCX_PAD_PUTN_BYTE(schar, uchar)
NCX_PAD_PUTN_BYTE(schar, short)
NCX_PAD_PUTN_BYTE(schar, int)
NCX_PAD_PUTN_BYTE(schar, long)
NCX_PAD_PUTN_BYTE(schar, float)
NCX_PAD_PUTN_BYTE(schar, double)
NCX_PAD_PUTN_BYTE(schar, longlong)
NCX_PAD_PUTN_BYTE(schar, ushort)
NCX_PAD_PUTN_BYTE(schar, uint)
NCX_PAD_PUTN_BYTE(schar, ulonglong)


/* uchar ---------------------------------------------------------------------*/
dnl
dnl NCX_GETN_BYTE(uchar, schar)
int
APIPrefix`x_getn_'NC_TYPE(uchar)_schar(const void **xpp, IntType nelems, schar *tp)
{
    int status = NC_NOERR;
    uchar *xp = (uchar *)(*xpp);

    while (nelems-- != 0) {
        if (*xp > SCHAR_MAX) {
            *tp = NC_FILL_BYTE;
       	    DEBUG_ASSIGN_ERROR(status, NC_ERANGE)
            SKIP_LOOP(xp, tp)
        }
	*tp++ = (schar) *xp++; /* type cast from uchar to schar */
    }

    *xpp = (const void *)xp;
    return status;
}
dnl NCX_GETN_BYTE(uchar, uchar)
int
APIPrefix`x_getn_'NC_TYPE(uchar)_uchar(const void **xpp, IntType nelems, uchar *tp)
{
	NCX_GETN_Byte_Body
}
NCX_GETN_BYTE(uchar, short)
NCX_GETN_BYTE(uchar, int)
NCX_GETN_BYTE(uchar, long)
NCX_GETN_BYTE(uchar, float)
NCX_GETN_BYTE(uchar, double)
NCX_GETN_BYTE(uchar, longlong)
NCX_GETN_BYTE(uchar, ushort)
NCX_GETN_BYTE(uchar, uint)
NCX_GETN_BYTE(uchar, ulonglong)

dnl NCX_PAD_GETN_BYTE(uchar, schar)
int
APIPrefix`x_pad_getn_'NC_TYPE(uchar)_schar(const void **xpp, IntType nelems, schar *tp)
{
    int status = NC_NOERR;
    IntType rndup = nelems % X_ALIGN;
    uchar *xp = (uchar *) *xpp;

    if (rndup) rndup = X_ALIGN - rndup;

    while (nelems-- != 0) {
        if (*xp > SCHAR_MAX) {
            *tp = NC_FILL_BYTE;
            DEBUG_ASSIGN_ERROR(status, NC_ERANGE)
            SKIP_LOOP(xp, tp)
        }
        *tp++ = (schar) *xp++; /* type cast from uchar to schar */
    }

    *xpp = (void *)(xp + rndup);
    return status;
}
dnl NCX_PAD_GETN_BYTE(uchar, uchar)
int
APIPrefix`x_pad_getn_'NC_TYPE(uchar)_uchar(const void **xpp, IntType nelems, uchar *tp)
{
	NCX_PAD_GETN_Byte_Body
}
NCX_PAD_GETN_BYTE(uchar, short)
NCX_PAD_GETN_BYTE(uchar, int)
NCX_PAD_GETN_BYTE(uchar, long)
NCX_PAD_GETN_BYTE(uchar, float)
NCX_PAD_GETN_BYTE(uchar, double)
NCX_PAD_GETN_BYTE(uchar, longlong)
NCX_PAD_GETN_BYTE(uchar, ushort)
NCX_PAD_GETN_BYTE(uchar, uint)
NCX_PAD_GETN_BYTE(uchar, ulonglong)

dnl NCX_PUTN_BYTE(uchar, schar)
int
APIPrefix`x_putn_'NC_TYPE(uchar)_schar(void **xpp, IntType nelems, const schar *tp, void *fillp)
{
    int status = NC_NOERR;
    uchar *xp = (uchar *) *xpp;

    while (nelems-- != 0) {
        if (*tp < 0) {
            FillValue(uchar, xp)
            DEBUG_ASSIGN_ERROR(status, NC_ERANGE)
            SKIP_LOOP(xp, tp)
        }
        *xp++ = (uchar) (signed) *tp++; /* type cast from schar to uchar */
    }

    *xpp = (void *)xp;
    return status;
}
dnl NCX_PUTN_BYTE(uchar, uchar)
int
APIPrefix`x_putn_'NC_TYPE(uchar)_uchar(void **xpp, IntType nelems, const uchar *tp, void *fillp)
{
	NCX_PUTN_Byte_Body
}
NCX_PUTN_BYTE(uchar, short)
NCX_PUTN_BYTE(uchar, int)
NCX_PUTN_BYTE(uchar, long)
NCX_PUTN_BYTE(uchar, float)
NCX_PUTN_BYTE(uchar, double)
NCX_PUTN_BYTE(uchar, longlong)
NCX_PUTN_BYTE(uchar, ushort)
NCX_PUTN_BYTE(uchar, uint)
NCX_PUTN_BYTE(uchar, ulonglong)

dnl NCX_PAD_PUTN_BYTE(uchar, schar)
int
APIPrefix`x_pad_putn_'NC_TYPE(uchar)_schar(void **xpp, IntType nelems, const schar *tp, void *fillp)
{
    int status = NC_NOERR;
    IntType rndup = nelems % X_ALIGN;
    uchar *xp = (uchar *) *xpp;

    if (rndup) rndup = X_ALIGN - rndup;

    while (nelems-- != 0) {
        if (*tp < 0) {
            FillValue(uchar, xp)
            DEBUG_ASSIGN_ERROR(status, NC_ERANGE)
            SKIP_LOOP(xp, tp)
        }
        *xp++ = (uchar) (signed) *tp++; /* type cast from schar to uchar */
    }

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

    *xpp = (void *)xp;
    return status;
}
dnl NCX_PAD_PUTN_UCHAR(uchar, uchar)
int
APIPrefix`x_pad_putn_'NC_TYPE(uchar)_uchar(void **xpp, IntType nelems, const uchar *tp, void *fillp)
{
	NCX_PAD_PUTN_Byte_Body
}
NCX_PAD_PUTN_BYTE(uchar, short)
NCX_PAD_PUTN_BYTE(uchar, int)
NCX_PAD_PUTN_BYTE(uchar, long)
NCX_PAD_PUTN_BYTE(uchar, float)
NCX_PAD_PUTN_BYTE(uchar, double)
NCX_PAD_PUTN_BYTE(uchar, longlong)
NCX_PAD_PUTN_BYTE(uchar, ushort)
NCX_PAD_PUTN_BYTE(uchar, uint)
NCX_PAD_PUTN_BYTE(uchar, ulonglong)

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

#if X_SIZEOF_SHORT == SIZEOF_SHORT
/* optimized version */
int
APIPrefix`x_getn_'NC_TYPE(short)_short(const void **xpp, IntType nelems, short *tp)
{
#ifdef WORDS_BIGENDIAN
	(void) memcpy(tp, *xpp, (size_t)nelems * SIZEOF_SHORT);
# else
	swapn2b(tp, *xpp, nelems);
# endif
	*xpp = (const void *)((const char *)(*xpp) + nelems * X_SIZEOF_SHORT);
	return NC_NOERR;
}
#else
NCX_GETN(short, short)
#endif
NCX_GETN(short, schar)
NCX_GETN(short, int)
NCX_GETN(short, long)
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, long)
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
APIPrefix`x_putn_'NC_TYPE(short)_short(void **xpp, IntType nelems, const short *tp, void *fillp)
{
#ifdef WORDS_BIGENDIAN
	(void) memcpy(*xpp, tp, (size_t)nelems * X_SIZEOF_SHORT);
# else
	swapn2b(*xpp, tp, nelems);
# endif
	*xpp = (void *)((char *)(*xpp) + nelems * X_SIZEOF_SHORT);
	return NC_NOERR;
}
#else
NCX_PUTN(short, short)
#endif
NCX_PUTN(short, schar)
NCX_PUTN(short, int)
NCX_PUTN(short, long)
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, long)
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
APIPrefix`x_getn_'NC_TYPE(ushort)_ushort(const void **xpp, IntType nelems, unsigned short *tp)
{
#ifdef WORDS_BIGENDIAN
	(void) memcpy(tp, *xpp, (size_t)nelems * SIZEOF_USHORT);
# else
	swapn2b(tp, *xpp, nelems);
# endif
	*xpp = (const void *)((const char *)(*xpp) + nelems * X_SIZEOF_USHORT);
	return NC_NOERR;
}
#else
NCX_GETN(ushort, ushort)
#endif
NCX_GETN(ushort, schar)
NCX_GETN(ushort, short)
NCX_GETN(ushort, int)
NCX_GETN(ushort, long)
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, short)
NCX_PAD_GETN_SHORT(ushort, int)
NCX_PAD_GETN_SHORT(ushort, long)
NCX_PAD_GETN_SHORT(ushort, float)
NCX_PAD_GETN_SHORT(ushort, double)
NCX_PAD_GETN_SHORT(ushort, uchar)
NCX_PAD_GETN_SHORT(ushort, ushort)
NCX_PAD_GETN_SHORT(ushort, uint)
NCX_PAD_GETN_SHORT(ushort, longlong)
NCX_PAD_GETN_SHORT(ushort, ulonglong)

#if X_SIZEOF_USHORT == SIZEOF_USHORT
/* optimized version */
int
APIPrefix`x_putn_'NC_TYPE(ushort)_ushort(void **xpp, IntType nelems, const unsigned short *tp, void *fillp)
{
#ifdef WORDS_BIGENDIAN
	(void) memcpy(*xpp, tp, (size_t)nelems * X_SIZEOF_USHORT);
# else
	swapn2b(*xpp, tp, nelems);
# endif
	*xpp = (void *)((char *)(*xpp) + nelems * X_SIZEOF_USHORT);
	return NC_NOERR;
}
#else
NCX_PUTN(ushort, ushort)
#endif
NCX_PUTN(ushort, schar)
NCX_PUTN(ushort, short)
NCX_PUTN(ushort, int)
NCX_PUTN(ushort, long)
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, long)
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
APIPrefix`x_getn_'NC_TYPE(int)_int(const void **xpp, IntType nelems, int *tp)
{
#ifdef WORDS_BIGENDIAN
	(void) memcpy(tp, *xpp, (size_t)nelems * SIZEOF_INT);
# else
	swapn4b(tp, *xpp, nelems);
# endif
	*xpp = (const void *)((const char *)(*xpp) + nelems * X_SIZEOF_INT);
	return NC_NOERR;
}
#else
NCX_GETN(int, int)
#endif
NCX_GETN(int, schar)
NCX_GETN(int, short)
NCX_GETN(int, long)
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
APIPrefix`x_putn_'NC_TYPE(int)_int(void **xpp, IntType nelems, const int *tp, void *fillp)
{
#ifdef WORDS_BIGENDIAN
	(void) memcpy(*xpp, tp, (size_t)nelems * X_SIZEOF_INT);
# else
	swapn4b(*xpp, tp, nelems);
# endif
	*xpp = (void *)((char *)(*xpp) + nelems * X_SIZEOF_INT);
	return NC_NOERR;
}
#else
NCX_PUTN(int, int)
#endif
NCX_PUTN(int, schar)
NCX_PUTN(int, short)
NCX_PUTN(int, long)
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
APIPrefix`x_getn_'NC_TYPE(uint)_uint(const void **xpp, IntType nelems, unsigned int *tp)
{
#ifdef WORDS_BIGENDIAN
	(void) memcpy(tp, *xpp, (size_t)nelems * SIZEOF_UINT);
# else
	swapn4b(tp, *xpp, nelems);
# endif
	*xpp = (const void *)((const char *)(*xpp) + nelems * X_SIZEOF_UINT);
	return NC_NOERR;
}
#else
NCX_GETN(uint, uint)
#endif
NCX_GETN(uint, schar)
NCX_GETN(uint, short)
NCX_GETN(uint, int)
NCX_GETN(uint, long)
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
APIPrefix`x_putn_'NC_TYPE(uint)_uint(void **xpp, IntType nelems, const unsigned int *tp, void *fillp)
{
#ifdef WORDS_BIGENDIAN
	(void) memcpy(*xpp, tp, (size_t)nelems * X_SIZEOF_UINT);
# else
	swapn4b(*xpp, tp, nelems);
# endif
	*xpp = (void *)((char *)(*xpp) + nelems * X_SIZEOF_UINT);
	return NC_NOERR;
}
#else
NCX_PUTN(uint, uint)
#endif
NCX_PUTN(uint, schar)
NCX_PUTN(uint, short)
NCX_PUTN(uint, int)
NCX_PUTN(uint, long)
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
APIPrefix`x_getn_'NC_TYPE(float)_float(const void **xpp, IntType nelems, float *tp)
{
#ifdef WORDS_BIGENDIAN
	(void) memcpy(tp, *xpp, (size_t)nelems * SIZEOF_FLOAT);
# else
	swapn4b(tp, *xpp, nelems);
# endif
	*xpp = (const void *)((const char *)(*xpp) + nelems * X_SIZEOF_FLOAT);
	return NC_NOERR;
}
#elif defined(vax) && vax != 0
int
APIPrefix`x_getn_'NC_TYPE(float)_float(const void **xpp, IntType nfloats, float *ip)
{
	float *const end = ip + nfloats;

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

		ip++;
		*xpp = (char *)(*xpp) + X_SIZEOF_FLOAT;
	}
	return NC_NOERR;
}
#else
int
APIPrefix`x_getn_'NC_TYPE(float)_float(const void **xpp, IntType nelems, float *tp)
{
	const char *xp = *xpp;
	int status = NC_NOERR;

	for( ; nelems != 0; nelems--, xp += X_SIZEOF_FLOAT, tp++)
	{
		const int lstatus = APIPrefix`x_get_'NC_TYPE(float)_float(xp, tp, fillp);
		if (status == NC_NOERR) /* report the first encountered error */
			status = lstatus;
	}

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

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

int
APIPrefix`x_putn_'NC_TYPE(float)_float(void **xpp, IntType nelems, const float *tp, void *fillp)
#if X_SIZEOF_FLOAT == SIZEOF_FLOAT && !defined(NO_IEEE_FLOAT)
/* optimized version */
{
#ifdef WORDS_BIGENDIAN
	(void) memcpy(*xpp, tp, (size_t)nelems * X_SIZEOF_FLOAT);
# else
	swapn4b(*xpp, tp, nelems);
# endif
	*xpp = (void *)((char *)(*xpp) + nelems * X_SIZEOF_FLOAT);
	return NC_NOERR;
}
#elif defined(vax) && vax != 0
{
	const float *const end = tp + nelems;

	while (tp < end) {
		PUT_VAX_DFLOAT_Body(`(*xpp)')
		tp++;
		*xpp = (char *)(*xpp) + X_SIZEOF_FLOAT;
	}
	return NC_NOERR;
}
#else
{
	char *xp = *xpp;
	int status = NC_NOERR;

	for( ; nelems != 0; nelems--, xp += X_SIZEOF_FLOAT, tp++) {
		int lstatus = APIPrefix`x_put_'NC_TYPE(float)_float(xp, tp, fillp);
		if (status == NC_NOERR) /* report the first encountered error */
			status = lstatus;
	}

	*xpp = (void *)xp;
	return status;
}
#endif
NCX_PUTN(float, schar)
NCX_PUTN(float, short)
NCX_PUTN(float, int)
NCX_PUTN(float, long)
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
APIPrefix`x_getn_'NC_TYPE(double)_double(const void **xpp, IntType nelems, double *tp)
{
#ifdef WORDS_BIGENDIAN
	(void) memcpy(tp, *xpp, (size_t)nelems * SIZEOF_DOUBLE);
# else
	swapn8b(tp, *xpp, nelems);
# endif
	*xpp = (const void *)((const char *)(*xpp) + nelems * X_SIZEOF_DOUBLE);
	return NC_NOERR;
}
#elif defined(vax) && vax != 0
int
APIPrefix`x_getn_'NC_TYPE(double)_double(const void **xpp, IntType ndoubles, double *ip)
{
	double *const end = ip + ndoubles;

	while (ip < end)
	{
GET_VAX_DDOUBLE_Body(`(*xpp)')
		ip++;
		*xpp = (char *)(*xpp) + X_SIZEOF_DOUBLE;
	}
	return NC_NOERR;
}
	/* vax */
#else
int
APIPrefix`x_getn_'NC_TYPE(double)_double(const void **xpp, IntType nelems, double *tp)
{
	const char *xp = *xpp;
	int status = NC_NOERR;

	for( ; nelems != 0; nelems--, xp += X_SIZEOF_DOUBLE, tp++)
	{
		const int lstatus = APIPrefix`x_get_'NC_TYPE(double)_double(xp, tp, fillp);
		if (status == NC_NOERR) /* report the first encountered error */
			status = lstatus;
	}

	*xpp = (const void *)xp;
	return status;
}
#endif
NCX_GETN(double, schar)
NCX_GETN(double, short)
NCX_GETN(double, int)
NCX_GETN(double, long)
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
APIPrefix`x_putn_'NC_TYPE(double)_double(void **xpp, IntType nelems, const double *tp, void *fillp)
{
#ifdef WORDS_BIGENDIAN
	(void) memcpy(*xpp, tp, (size_t)nelems * X_SIZEOF_DOUBLE);
# else
	swapn8b(*xpp, tp, nelems);
# endif
	*xpp = (void *)((char *)(*xpp) + nelems * X_SIZEOF_DOUBLE);
	return NC_NOERR;
}
#elif defined(vax) && vax != 0
int
APIPrefix`x_putn_'NC_TYPE(double)_double(void **xpp, IntType ndoubles, const double *ip, void *fillp)
{
	const double *const end = ip + ndoubles;

	while (ip < end)
	{
PUT_VAX_DDOUBLE_Body(`(*xpp)')
		ip++;
		*xpp = (char *)(*xpp) + X_SIZEOF_DOUBLE;
	}
	return NC_NOERR;
}
	/* vax */
#else
int
APIPrefix`x_putn_'NC_TYPE(double)_double(void **xpp, IntType nelems, const double *tp, void *fillp)
{
	char *xp = *xpp;
	int status = NC_NOERR;

	for( ; nelems != 0; nelems--, xp += X_SIZEOF_DOUBLE, tp++)
	{
		int lstatus = APIPrefix`x_put_'NC_TYPE(double)_double(xp, tp, fillp);
		if (status == NC_NOERR) /* report the first encountered error */
			status = lstatus;
	}

	*xpp = (void *)xp;
	return status;
}
#endif
NCX_PUTN(double, schar)
NCX_PUTN(double, short)
NCX_PUTN(double, int)
NCX_PUTN(double, long)
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_INT64 == SIZEOF_LONGLONG
/* optimized version */
int
APIPrefix`x_getn_'NC_TYPE(int64)_longlong(const void **xpp, IntType nelems, long long *tp)
{
#ifdef WORDS_BIGENDIAN
	(void) memcpy(tp, *xpp, (size_t)nelems * SIZEOF_LONG_LONG);
# else
	swapn8b(tp, *xpp, nelems);
# endif
	*xpp = (const void *)((const char *)(*xpp) + nelems * X_SIZEOF_INT64);
	return NC_NOERR;
}
#else
NCX_GETN(int64, longlong)
#endif
NCX_GETN(int64, schar)
NCX_GETN(int64, short)
NCX_GETN(int64, int)
NCX_GETN(int64, long)
NCX_GETN(int64, float)
NCX_GETN(int64, double)
NCX_GETN(int64, uchar)
NCX_GETN(int64, ushort)
NCX_GETN(int64, uint)
NCX_GETN(int64, ulonglong)

#if X_SIZEOF_INT64 == SIZEOF_LONGLONG
/* optimized version */
int
APIPrefix`x_putn_'NC_TYPE(int64)_longlong(void **xpp, IntType nelems, const long long *tp, void *fillp)
{
#ifdef WORDS_BIGENDIAN
	(void) memcpy(*xpp, tp, (size_t)nelems * X_SIZEOF_INT64);
# else
	swapn8b(*xpp, tp, nelems);
# endif
	*xpp = (void *)((char *)(*xpp) + nelems * X_SIZEOF_INT64);
	return NC_NOERR;
}
#else
NCX_PUTN(int64, longlong)
#endif
NCX_PUTN(int64, schar)
NCX_PUTN(int64, short)
NCX_PUTN(int64, int)
NCX_PUTN(int64, long)
NCX_PUTN(int64, float)
NCX_PUTN(int64, double)
NCX_PUTN(int64, uchar)
NCX_PUTN(int64, ushort)
NCX_PUTN(int64, uint)
NCX_PUTN(int64, ulonglong)

/* uint64 --------------------------------------------------------------------*/

#if X_SIZEOF_UINT64 == SIZEOF_ULONGLONG
/* optimized version */
int
APIPrefix`x_getn_'NC_TYPE(uint64)_ulonglong(const void **xpp, IntType nelems, unsigned long long *tp)
{
#ifdef WORDS_BIGENDIAN
	(void) memcpy(tp, *xpp, (size_t)nelems * SIZEOF_UNSIGNED_LONG_LONG);
# else
	swapn8b(tp, *xpp, nelems);
# endif
	*xpp = (const void *)((const char *)(*xpp) + nelems * X_SIZEOF_UINT64);
	return NC_NOERR;
}
#else
NCX_GETN(uint64, ulonglong)
#endif
NCX_GETN(uint64, schar)
NCX_GETN(uint64, short)
NCX_GETN(uint64, int)
NCX_GETN(uint64, long)
NCX_GETN(uint64, float)
NCX_GETN(uint64, double)
NCX_GETN(uint64, longlong)
NCX_GETN(uint64, uchar)
NCX_GETN(uint64, ushort)
NCX_GETN(uint64, uint)

#if X_SIZEOF_UINT64 == SIZEOF_ULONGLONG
/* optimized version */
int
APIPrefix`x_putn_'NC_TYPE(uint64)_ulonglong(void **xpp, IntType nelems, const unsigned long long *tp, void *fillp)
{
#ifdef WORDS_BIGENDIAN
	(void) memcpy(*xpp, tp, (size_t)nelems * X_SIZEOF_UINT64);
# else
	swapn8b(*xpp, tp, nelems);
# endif
	*xpp = (void *)((char *)(*xpp) + nelems * X_SIZEOF_UINT64);
	return NC_NOERR;
}
#else
NCX_PUTN(uint64, ulonglong)
#endif
NCX_PUTN(uint64, schar)
NCX_PUTN(uint64, short)
NCX_PUTN(uint64, int)
NCX_PUTN(uint64, long)
NCX_PUTN(uint64, float)
NCX_PUTN(uint64, double)
NCX_PUTN(uint64, longlong)
NCX_PUTN(uint64, uchar)
NCX_PUTN(uint64, ushort)
NCX_PUTN(uint64, uint)


/*
 * Other aggregate conversion functions.
 */

/* text */

int
APIPrefix`x_getn_text'(const void **xpp, IntType nelems, char *tp)
{
NCX_GETN_Byte_Body
}

int
APIPrefix`x_pad_getn_text'(const void **xpp, IntType nelems, char *tp)
{
NCX_PAD_GETN_Byte_Body
}

int
APIPrefix`x_putn_text'(void **xpp, IntType nelems, const char *tp)
{
NCX_PUTN_Byte_Body
}

int
APIPrefix`x_pad_putn_text'(void **xpp, IntType nelems, const char *tp)
{
NCX_PAD_PUTN_Byte_Body
}


/* opaque */

int
APIPrefix`x_getn_void'(const void **xpp, IntType nelems, void *tp)
{
NCX_GETN_Byte_Body
}

int
APIPrefix`x_pad_getn_void'(const void **xpp, IntType nelems, void *tp)
{
NCX_PAD_GETN_Byte_Body
}

int
APIPrefix`x_putn_void'(void **xpp, IntType nelems, const void *tp)
{
NCX_PUTN_Byte_Body
}

int
APIPrefix`x_pad_putn_void'(void **xpp, IntType nelems, const void *tp)
{
NCX_PAD_PUTN_Byte_Body
}
