netcdf-c/libsrc/ncx.c
Quincey Koziol cd71eb525c Corrected "BAIL" macros to avoid infinite loop when logging is disabled and an
error occurs after an "exit:" label.

Corrected a dozen Coverity errors (mainly allocation issues, along with a few
    other things):
        711711, 711802, 711803, 711905, 970825, 996123, 996124, 1025787,
        1047274, 1130013, 1130014, 1139538

Refactored internal fill-value code to correctly handle string types, and
    especially to allow NULL pointers and null strings (ie. "") to be
    distinguished.  The code now avoids partially aliasing the two together
    (which only happened on the 'write' side of things and wasn't reflected on
    the 'read' side, adding to the previous confusion).

    Probably still weak on handling fill-values of variable-length and compound
    datatypes.

Refactored the recursive metadata reads a bit more, to process HDF5 named
    datatypes and datasets immediately, avoiding chewing up memory for those
    types of objects, etc.

Finished uncommenting and updating the nc_test4/tst_fills2.c code (as I'm
    proceeding alphabetically through the nc_test4 code files).
2013-12-29 01:12:43 -06:00

8392 lines
194 KiB
C

/* Do not edit this file. It is produced from the corresponding .m4 source */
/*
* 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,v 2.58 2010/05/26 18:11:08 dmh Exp $ */
/*
* An external data representation interface.
*/
#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 LONG_LONG_MIN
#define LONG_LONG_MIN LLONG_MIN
#endif
#ifndef ULONG_LONG_MAX
#define ULONG_LONG_MAX ULLONG_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))
/*
* 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
static void
swap4b(void *dst, const void *src)
{
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 */
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 */
/*
* Primitive numeric conversion functions.
*/
/* x_schar */
/* We don't implement any x_schar 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;
}
int
ncx_get_short_schar(const void *xp, schar *ip)
{
ix_short xx;
get_ix_short(xp, &xx);
*ip = xx;
if(xx > SCHAR_MAX || xx < SCHAR_MIN)
return NC_ERANGE;
return ENOERR;
}
int
ncx_get_short_uchar(const void *xp, uchar *ip)
{
ix_short xx;
get_ix_short(xp, &xx);
*ip = xx;
if(xx > UCHAR_MAX || xx < 0)
return NC_ERANGE;
return ENOERR;
}
int
ncx_get_short_short(const void *xp, short *ip)
{
#if SIZEOF_IX_SHORT == SIZEOF_SHORT && IX_SHORT_MAX == SHORT_MAX
get_ix_short(xp, (ix_short *)ip);
return ENOERR;
#else
ix_short xx;
get_ix_short(xp, &xx);
*ip = xx;
# if IX_SHORT_MAX > SHORT_MAX
if(xx > SHORT_MAX || xx < SHORT_MIN)
return NC_ERANGE;
# endif
return ENOERR;
#endif
}
int
ncx_get_short_int(const void *xp, int *ip)
{
#if SIZEOF_IX_SHORT == SIZEOF_INT && IX_SHORT_MAX == INT_MAX
get_ix_short(xp, (ix_short *)ip);
return ENOERR;
#else
ix_short xx;
get_ix_short(xp, &xx);
*ip = xx;
# if IX_SHORT_MAX > INT_MAX
if(xx > INT_MAX || xx < INT_MIN)
return NC_ERANGE;
# endif
return ENOERR;
#endif
}
int
ncx_get_short_uint(const void *xp, unsigned int *ip)
{
#if SIZEOF_IX_SHORT == SIZEOF_INT && IX_SHORT_MAX == INT_MAX
get_ix_short(xp, (ix_short *)ip);
return ENOERR;
#else
ix_short xx;
get_ix_short(xp, &xx);
*ip = xx;
# if IX_SHORT_MAX > INT_MAX
if(xx > UINT_MAX || xx < 0)
return NC_ERANGE;
# endif
return ENOERR;
#endif
}
int
ncx_get_short_longlong(const void *xp, long long *ip)
{
#if SIZEOF_IX_SHORT == SIZEOF_LONG_LONG && IX_SHORT_MAX == LONG_LONG_MAX
get_ix_short(xp, (ix_short *)ip);
return ENOERR;
#else
/* assert(LONG_LONG_MAX >= X_SHORT_MAX); */
ix_short xx;
get_ix_short(xp, &xx);
*ip = xx;
return ENOERR;
#endif
}
int
ncx_get_short_ulonglong(const void *xp, unsigned long long *ip)
{
#if SIZEOF_IX_SHORT == SIZEOF_LONG && IX_SHORT_MAX == LONG_MAX
get_ix_short(xp, (ix_short *)ip);
return ENOERR;
#else
/* assert(LONG_LONG_MAX >= X_SHORT_MAX); */
ix_short xx;
get_ix_short(xp, &xx);
*ip = xx;
if(xx < 0)
return NC_ERANGE;
return ENOERR;
#endif
}
int
ncx_get_short_float(const void *xp, float *ip)
{
ix_short xx;
get_ix_short(xp, &xx);
*ip = xx;
#if 0 /* TODO: determine when necessary */
if(xx > FLT_MAX || xx < (-FLT_MAX))
return NC_ERANGE;
#endif
return ENOERR;
}
int
ncx_get_short_double(const void *xp, double *ip)
{
/* assert(DBL_MAX >= X_SHORT_MAX); */
ix_short xx;
get_ix_short(xp, &xx);
*ip = xx;
return ENOERR;
}
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;
}
int
ncx_put_short_uchar(void *xp, const uchar *ip)
{
uchar *cp = (uchar *) xp;
*cp++ = 0;
*cp = *ip;
return ENOERR;
}
int
ncx_put_short_short(void *xp, const short *ip)
{
#if SIZEOF_IX_SHORT == SIZEOF_SHORT && X_SHORT_MAX == SHORT_MAX
put_ix_short(xp, (const ix_short *)ip);
return ENOERR;
#else
ix_short xx = (ix_short)*ip;
put_ix_short(xp, &xx);
# if X_SHORT_MAX < SHORT_MAX
if(*ip > X_SHORT_MAX || *ip < X_SHORT_MIN)
return NC_ERANGE;
# endif
return ENOERR;
#endif
}
int
ncx_put_short_int(void *xp, const int *ip)
{
#if SIZEOF_IX_SHORT == SIZEOF_INT && X_SHORT_MAX == INT_MAX
put_ix_short(xp, (const ix_short *)ip);
return ENOERR;
#else
ix_short xx = (ix_short)*ip;
put_ix_short(xp, &xx);
# if X_SHORT_MAX < INT_MAX
if(*ip > X_SHORT_MAX || *ip < X_SHORT_MIN)
return NC_ERANGE;
# endif
return ENOERR;
#endif
}
int
ncx_put_short_uint(void *xp, const unsigned int *ip)
{
#if SIZEOF_IX_SHORT == SIZEOF_INT && X_SHORT_MAX == INT_MAX
put_ix_short(xp, (const ix_short *)ip);
return ENOERR;
#else
ix_short xx = (ix_short)*ip;
put_ix_short(xp, &xx);
# if X_SHORT_MAX < INT_MAX
if(*ip > X_SHORT_MAX)
return NC_ERANGE;
# endif
return ENOERR;
#endif
}
int
ncx_put_short_longlong(void *xp, const long long *ip)
{
#if SIZEOF_IX_SHORT == SIZEOF_LONG_LONG && X_SHORT_MAX == LONG_LONG_MAX
put_ix_short(xp, (const ix_short *)ip);
return ENOERR;
#else
ix_short xx = (ix_short)*ip;
put_ix_short(xp, &xx);
# if X_SHORT_MAX < LONG_LONG_MAX
if(*ip > X_SHORT_MAX || *ip < X_SHORT_MIN)
return NC_ERANGE;
# endif
return ENOERR;
#endif
}
int
ncx_put_short_ulonglong(void *xp, const unsigned long long *ip)
{
#if SIZEOF_IX_SHORT == SIZEOF_LONG_LONG && X_SHORT_MAX == LONG_LONG_MAX
put_ix_short(xp, (const ix_short *)ip);
return ENOERR;
#else
ix_short xx = (ix_short)*ip;
put_ix_short(xp, &xx);
# if X_SHORT_MAX < LONG_LONG_MAX
if(*ip > X_SHORT_MAX)
return NC_ERANGE;
# endif
return ENOERR;
#endif
}
int
ncx_put_short_float(void *xp, const float *ip)
{
ix_short xx = *ip;
put_ix_short(xp, &xx);
if(*ip > X_SHORT_MAX || *ip < X_SHORT_MIN)
return NC_ERANGE;
return ENOERR;
}
int
ncx_put_short_double(void *xp, const double *ip)
{
ix_short xx = *ip;
put_ix_short(xp, &xx);
if(*ip > X_SHORT_MAX || *ip < X_SHORT_MIN)
return NC_ERANGE;
return ENOERR;
}
/* 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);
}
int
ncx_get_int_schar(const void *xp, schar *ip)
{
ix_int xx;
get_ix_int(xp, &xx);
*ip = xx;
if(xx > SCHAR_MAX || xx < SCHAR_MIN)
return NC_ERANGE;
return ENOERR;
}
int
ncx_get_int_uchar(const void *xp, uchar *ip)
{
ix_int xx;
get_ix_int(xp, &xx);
*ip = xx;
if(xx > UCHAR_MAX || xx < 0)
return NC_ERANGE;
return ENOERR;
}
int
ncx_get_int_short(const void *xp, short *ip)
{
#if SIZEOF_IX_INT == SIZEOF_SHORT && IX_INT_MAX == SHORT_MAX
get_ix_int(xp, (ix_int *)ip);
return ENOERR;
#else
ix_int xx;
get_ix_int(xp, &xx);
*ip = xx;
# if IX_INT_MAX > SHORT_MAX
if(xx > SHORT_MAX || xx < SHORT_MIN)
return NC_ERANGE;
# endif
return ENOERR;
#endif
}
int
ncx_get_int_int(const void *xp, int *ip)
{
#if SIZEOF_IX_INT == SIZEOF_INT && IX_INT_MAX == INT_MAX
get_ix_int(xp, (ix_int *)ip);
return ENOERR;
#else
ix_int xx;
get_ix_int(xp, &xx);
*ip = xx;
# if IX_INT_MAX > INT_MAX
if(xx > INT_MAX || xx < INT_MIN)
return NC_ERANGE;
# endif
return ENOERR;
#endif
}
int
ncx_get_int_uint(const void *xp, unsigned int *ip)
{
ix_int xx;
get_ix_int(xp, &xx);
*ip = xx;
if(xx < 0)
return NC_ERANGE;
return ENOERR;
}
int
ncx_get_int_longlong(const void *xp, long long *ip)
{
ix_int xx;
get_ix_int(xp, &xx);
*ip = xx;
return ENOERR;
}
int
ncx_get_int_ulonglong(const void *xp, unsigned long long *ip)
{
ix_int xx;
get_ix_int(xp, &xx);
*ip = xx;
if(xx < 0)
return NC_ERANGE;
return ENOERR;
}
int
ncx_get_int_float(const void *xp, float *ip)
{
ix_int xx;
get_ix_int(xp, &xx);
*ip = xx;
#if 0 /* TODO: determine when necessary */
if(xx > FLT_MAX || xx < (-FLT_MAX))
return NC_ERANGE;
#endif
return ENOERR;
}
int
ncx_get_int_double(const void *xp, double *ip)
{
/* assert((DBL_MAX >= X_INT_MAX); */
ix_int xx;
get_ix_int(xp, &xx);
*ip = xx;
return ENOERR;
}
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;
}
int
ncx_put_int_uchar(void *xp, const uchar *ip)
{
uchar *cp = (uchar *) xp;
*cp++ = 0x00;
*cp++ = 0x00;
*cp++ = 0x00;
*cp = *ip;
return ENOERR;
}
int
ncx_put_int_short(void *xp, const short *ip)
{
#if SIZEOF_IX_INT == SIZEOF_SHORT && IX_INT_MAX == SHORT_MAX
put_ix_int(xp, (ix_int *)ip);
return ENOERR;
#else
ix_int xx = (ix_int)(*ip);
put_ix_int(xp, &xx);
# if IX_INT_MAX < SHORT_MAX
if(*ip > X_INT_MAX || *ip < X_INT_MIN)
return NC_ERANGE;
# endif
return ENOERR;
#endif
}
int
ncx_put_int_int(void *xp, const int *ip)
{
#if SIZEOF_IX_INT == SIZEOF_INT && IX_INT_MAX == INT_MAX
put_ix_int(xp, (ix_int *)ip);
return ENOERR;
#else
ix_int xx = (ix_int)(*ip);
put_ix_int(xp, &xx);
# if IX_INT_MAX < INT_MAX
if(*ip > X_INT_MAX || *ip < X_INT_MIN)
return NC_ERANGE;
# endif
return ENOERR;
#endif
}
int
ncx_put_int_uint(void *xp, const unsigned int *ip)
{
#if SIZEOF_IX_INT == SIZEOF_INT && IX_INT_MAX == INT_MAX
put_ix_int(xp, (ix_int *)ip);
return ENOERR;
#else
ix_int xx = (ix_int)(*ip);
put_ix_int(xp, &xx);
if(*ip > X_UINT_MAX)
return NC_ERANGE;
return ENOERR;
#endif
}
int
ncx_put_int_longlong(void *xp, const longlong *ip)
{
#if SIZEOF_IX_INT == SIZEOF_LONG && IX_INT_MAX == LONG_MAX
put_ix_int(xp, (ix_int *)ip);
return ENOERR;
#else
ix_int xx = (ix_int)(*ip);
put_ix_int(xp, &xx);
# if IX_INT_MAX < LONG_LONG_MAX
if(*ip > X_INT_MAX || *ip < X_INT_MIN)
return NC_ERANGE;
# endif
return ENOERR;
#endif
}
int
ncx_put_int_ulonglong(void *xp, const unsigned long long *ip)
{
#if SIZEOF_IX_INT == SIZEOF_LONG && IX_INT_MAX == LONG_MAX
put_ix_int(xp, (ix_int *)ip);
return ENOERR;
#else
ix_int xx = (ix_int)(*ip);
put_ix_int(xp, &xx);
# if IX_INT_MAX < LONG_MAX
if(*ip > X_INT_MAX)
return NC_ERANGE;
# endif
return ENOERR;
#endif
}
int
ncx_put_int_float(void *xp, const float *ip)
{
ix_int xx = (ix_int)(*ip);
put_ix_int(xp, &xx);
if(*ip > (double)X_INT_MAX || *ip < (double)X_INT_MIN)
return NC_ERANGE;
return ENOERR;
}
int
ncx_put_int_double(void *xp, const double *ip)
{
ix_int xx = (ix_int)(*ip);
put_ix_int(xp, &xx);
if(*ip > X_INT_MAX || *ip < X_INT_MIN)
return NC_ERANGE;
return ENOERR;
}
/* 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 */
};
static void
get_ix_float(const void *xp, float *ip)
{
struct vax_single *const vsp = (struct vax_single *) ip;
const struct ieee_single *const isp =
(const struct ieee_single *) xp;
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;
}
static void
put_ix_float(void *xp, const float *ip)
{
const struct vax_single *const vsp =
(const struct vax_single *)ip;
struct ieee_single *const isp = (struct ieee_single *) xp;
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;
}
/* vax */
#elif defined(_CRAY) && !defined(__crayx1)
/*
* Return the number of bytes until the next "word" boundary
* N.B. This is based on the very wierd 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;
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;
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;
}
else
{
const ieee_single_lo *isp = (const ieee_single_lo *) xp;
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;
}
}
static void
put_ix_float(void *xp, const float *ip)
{
if(word_align(xp) == 0)
{
ieee_single_hi *isp = (ieee_single_hi*)xp;
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;
}
}
else
{
ieee_single_lo *isp = (ieee_single_lo*)xp;
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;
}
}
}
#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
int
ncx_get_float_schar(const void *xp, schar *ip)
{
float xx;
get_ix_float(xp, &xx);
*ip = (schar) xx;
if(xx > SCHAR_MAX || xx < SCHAR_MIN)
return NC_ERANGE;
return ENOERR;
}
int
ncx_get_float_uchar(const void *xp, uchar *ip)
{
float xx;
get_ix_float(xp, &xx);
*ip = (uchar) xx;
if(xx > UCHAR_MAX || xx < 0)
return NC_ERANGE;
return ENOERR;
}
int
ncx_get_float_short(const void *xp, short *ip)
{
float xx;
get_ix_float(xp, &xx);
*ip = (short) xx;
if(xx > SHORT_MAX || xx < SHORT_MIN)
return NC_ERANGE;
return ENOERR;
}
int
ncx_get_float_int(const void *xp, int *ip)
{
float xx;
get_ix_float(xp, &xx);
*ip = (int) xx;
if(xx > (double)INT_MAX || xx < (double)INT_MIN)
return NC_ERANGE;
return ENOERR;
}
int
ncx_get_float_uint(const void *xp, unsigned int *ip)
{
float xx;
get_ix_float(xp, &xx);
*ip = (unsigned int) xx;
if(xx > (double)UINT_MAX || xx < 0)
return NC_ERANGE;
return ENOERR;
}
int
ncx_get_float_longlong(const void *xp, longlong *ip)
{
float xx;
get_ix_float(xp, &xx);
*ip = (longlong) xx;
if(xx > (double)LONG_LONG_MAX || xx < (double)LONG_LONG_MIN)
return NC_ERANGE;
return ENOERR;
}
int
ncx_get_float_ulonglong(const void *xp, unsigned long long *ip)
{
float xx;
get_ix_float(xp, &xx);
*ip = (longlong) xx;
if(xx > (double)ULONG_LONG_MAX || xx < 0)
return NC_ERANGE;
return ENOERR;
}
int
ncx_get_float_float(const void *xp, float *ip)
{
/* TODO */
get_ix_float(xp, ip);
return ENOERR;
}
int
ncx_get_float_double(const void *xp, double *ip)
{
/* TODO */
float xx;
get_ix_float(xp, &xx);
*ip = xx;
return ENOERR;
}
int
ncx_put_float_schar(void *xp, const schar *ip)
{
float xx = (float) *ip;
put_ix_float(xp, &xx);
return ENOERR;
}
int
ncx_put_float_uchar(void *xp, const uchar *ip)
{
float xx = (float) *ip;
put_ix_float(xp, &xx);
return ENOERR;
}
int
ncx_put_float_short(void *xp, const short *ip)
{
float xx = (float) *ip;
put_ix_float(xp, &xx);
#if 0 /* TODO: figure this out */
if((float)(*ip) > X_FLOAT_MAX || (float)(*ip) < X_FLOAT_MIN)
return NC_ERANGE;
#endif
return ENOERR;
}
int
ncx_put_float_int(void *xp, const int *ip)
{
float xx = (float) *ip;
put_ix_float(xp, &xx);
#if 1 /* TODO: figure this out */
if((float)(*ip) > X_FLOAT_MAX || (float)(*ip) < X_FLOAT_MIN)
return NC_ERANGE;
#endif
return ENOERR;
}
int
ncx_put_float_uint(void *xp, const unsigned int *ip)
{
float xx = (float) *ip;
put_ix_float(xp, &xx);
#if 1 /* TODO: figure this out */
if((float)(*ip) > X_FLOAT_MAX)
return NC_ERANGE;
#endif
return ENOERR;
}
int
ncx_put_float_longlong(void *xp, const longlong *ip)
{
float xx = (float) *ip;
put_ix_float(xp, &xx);
#if 1 /* TODO: figure this out */
if((float)(*ip) > X_FLOAT_MAX || (float)(*ip) < X_FLOAT_MIN)
return NC_ERANGE;
#endif
return ENOERR;
}
int
ncx_put_float_ulonglong(void *xp, const unsigned long long *ip)
{
float xx = (float) *ip;
put_ix_float(xp, &xx);
#if 1 /* TODO: figure this out */
if((float)(*ip) > X_FLOAT_MAX)
return NC_ERANGE;
#endif
return ENOERR;
}
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;
}
int
ncx_put_float_double(void *xp, const double *ip)
{
float xx = (float) *ip;
put_ix_float(xp, &xx);
if(*ip > X_FLOAT_MAX || *ip < X_FLOAT_MIN)
return NC_ERANGE;
return ENOERR;
}
/* 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 */
};
static void
get_ix_double(const void *xp, double *ip)
{
struct vax_double *const vdp =
(struct vax_double *)ip;
const struct ieee_double *const idp =
(const struct ieee_double *) xp;
{
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;
}
static void
put_ix_double(void *xp, const double *ip)
{
const struct vax_double *const vdp =
(const struct vax_double *)ip;
struct ieee_double *const idp =
(struct ieee_double *) xp;
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;
}
/* 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
int
ncx_get_double_schar(const void *xp, schar *ip)
{
double xx;
get_ix_double(xp, &xx);
*ip = (schar) xx;
if(xx > SCHAR_MAX || xx < SCHAR_MIN)
return NC_ERANGE;
return ENOERR;
}
int
ncx_get_double_uchar(const void *xp, uchar *ip)
{
double xx;
get_ix_double(xp, &xx);
*ip = (uchar) xx;
if(xx > UCHAR_MAX || xx < 0)
return NC_ERANGE;
return ENOERR;
}
int
ncx_get_double_short(const void *xp, short *ip)
{
double xx;
get_ix_double(xp, &xx);
*ip = (short) xx;
if(xx > SHORT_MAX || xx < SHORT_MIN)
return NC_ERANGE;
return ENOERR;
}
int
ncx_get_double_int(const void *xp, int *ip)
{
double xx;
get_ix_double(xp, &xx);
*ip = (int) xx;
if(xx > INT_MAX || xx < INT_MIN)
return NC_ERANGE;
return ENOERR;
}
int
ncx_get_double_uint(const void *xp, unsigned int *ip)
{
double xx;
get_ix_double(xp, &xx);
*ip = (unsigned int) xx;
if(xx > UINT_MAX || xx < 0)
return NC_ERANGE;
return ENOERR;
}
int
ncx_get_double_longlong(const void *xp, longlong *ip)
{
double xx;
get_ix_double(xp, &xx);
*ip = (longlong) xx;
if(xx > LONG_LONG_MAX || xx < LONG_LONG_MIN)
return NC_ERANGE;
return ENOERR;
}
int
ncx_get_double_ulonglong(const void *xp, unsigned long long *ip)
{
double xx;
get_ix_double(xp, &xx);
*ip = (unsigned longlong) xx;
if(xx > ULONG_LONG_MAX || xx < 0)
return NC_ERANGE;
return ENOERR;
}
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;
}
int
ncx_get_double_double(const void *xp, double *ip)
{
/* TODO */
get_ix_double(xp, ip);
return ENOERR;
}
int
ncx_put_double_schar(void *xp, const schar *ip)
{
double xx = (double) *ip;
put_ix_double(xp, &xx);
return ENOERR;
}
int
ncx_put_double_uchar(void *xp, const uchar *ip)
{
double xx = (double) *ip;
put_ix_double(xp, &xx);
return ENOERR;
}
int
ncx_put_double_short(void *xp, const short *ip)
{
double xx = (double) *ip;
put_ix_double(xp, &xx);
#if 0 /* TODO: figure this out */
if((double)(*ip) > X_DOUBLE_MAX || (double)(*ip) < X_DOUBLE_MIN)
return NC_ERANGE;
#endif
return ENOERR;
}
int
ncx_put_double_int(void *xp, const int *ip)
{
double xx = (double) *ip;
put_ix_double(xp, &xx);
#if 0 /* TODO: figure this out */
if((double)(*ip) > X_DOUBLE_MAX || (double)(*ip) < X_DOUBLE_MIN)
return NC_ERANGE;
#endif
return ENOERR;
}
int
ncx_put_double_uint(void *xp, const unsigned int *ip)
{
double xx = (double) *ip;
put_ix_double(xp, &xx);
#if 0 /* TODO: figure this out */
if((double)(*ip) > X_DOUBLE_MAX)
return NC_ERANGE;
#endif
return ENOERR;
}
int
ncx_put_double_longlong(void *xp, const longlong *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;
}
int
ncx_put_double_ulonglong(void *xp, const unsigned long long *ip)
{
double xx = (double) *ip;
put_ix_double(xp, &xx);
#if 1 /* TODO: figure this out */
if((double)(*ip) > X_DOUBLE_MAX)
return NC_ERANGE;
#endif
return ENOERR;
}
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;
}
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;
}
/* 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 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 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 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;
}
/*
* Aggregate numeric conversion functions.
*/
/* schar */
int
ncx_getn_schar_schar(const void **xpp, size_t nelems, schar *tp)
{
(void) memcpy(tp, *xpp, nelems);
*xpp = (void *)((char *)(*xpp) + nelems);
return ENOERR;
}
int
ncx_getn_schar_uchar(const void **xpp, size_t nelems, uchar *tp)
{
(void) memcpy(tp, *xpp, nelems);
*xpp = (void *)((char *)(*xpp) + nelems);
return ENOERR;
}
int
ncx_getn_schar_short(const void **xpp, size_t nelems, short *tp)
{
schar *xp = (schar *)(*xpp);
while(nelems-- != 0)
{
*tp++ = *xp++;
}
*xpp = (const void *)xp;
return ENOERR;
}
int
ncx_getn_schar_int(const void **xpp, size_t nelems, int *tp)
{
schar *xp = (schar *)(*xpp);
while(nelems-- != 0)
{
*tp++ = *xp++;
}
*xpp = (const void *)xp;
return ENOERR;
}
int
ncx_getn_schar_float(const void **xpp, size_t nelems, float *tp)
{
schar *xp = (schar *)(*xpp);
while(nelems-- != 0)
{
*tp++ = *xp++;
}
*xpp = (const void *)xp;
return ENOERR;
}
int
ncx_getn_schar_double(const void **xpp, size_t nelems, double *tp)
{
schar *xp = (schar *)(*xpp);
while(nelems-- != 0)
{
*tp++ = *xp++;
}
*xpp = (const void *)xp;
return ENOERR;
}
int
ncx_getn_schar_uint(const void **xpp, size_t nelems, uint *tp)
{
schar *xp = (schar *)(*xpp);
while(nelems-- != 0)
{
*tp++ = *xp++;
}
*xpp = (const void *)xp;
return ENOERR;
}
int
ncx_getn_schar_longlong(const void **xpp, size_t nelems, longlong *tp)
{
schar *xp = (schar *)(*xpp);
while(nelems-- != 0)
{
*tp++ = *xp++;
}
*xpp = (const void *)xp;
return ENOERR;
}
int
ncx_getn_schar_ulonglong(const void **xpp, size_t nelems, ulonglong *tp)
{
schar *xp = (schar *)(*xpp);
while(nelems-- != 0)
{
*tp++ = *xp++;
}
*xpp = (const void *)xp;
return ENOERR;
}
int
ncx_pad_getn_schar_schar(const void **xpp, size_t nelems, schar *tp)
{
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;
}
int
ncx_pad_getn_schar_uchar(const void **xpp, size_t nelems, uchar *tp)
{
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;
}
int
ncx_pad_getn_schar_short(const void **xpp, size_t nelems, short *tp)
{
size_t rndup = nelems % X_ALIGN;
schar *xp = (schar *) *xpp;
if(rndup)
rndup = X_ALIGN - rndup;
while(nelems-- != 0)
{
*tp++ = *xp++;
}
*xpp = (void *)(xp + rndup);
return ENOERR;
}
int
ncx_pad_getn_schar_int(const void **xpp, size_t nelems, int *tp)
{
size_t rndup = nelems % X_ALIGN;
schar *xp = (schar *) *xpp;
if(rndup)
rndup = X_ALIGN - rndup;
while(nelems-- != 0)
{
*tp++ = *xp++;
}
*xpp = (void *)(xp + rndup);
return ENOERR;
}
int
ncx_pad_getn_schar_float(const void **xpp, size_t nelems, float *tp)
{
size_t rndup = nelems % X_ALIGN;
schar *xp = (schar *) *xpp;
if(rndup)
rndup = X_ALIGN - rndup;
while(nelems-- != 0)
{
*tp++ = *xp++;
}
*xpp = (void *)(xp + rndup);
return ENOERR;
}
int
ncx_pad_getn_schar_double(const void **xpp, size_t nelems, double *tp)
{
size_t rndup = nelems % X_ALIGN;
schar *xp = (schar *) *xpp;
if(rndup)
rndup = X_ALIGN - rndup;
while(nelems-- != 0)
{
*tp++ = *xp++;
}
*xpp = (void *)(xp + rndup);
return ENOERR;
}
int
ncx_pad_getn_schar_uint(const void **xpp, size_t nelems, uint *tp)
{
size_t rndup = nelems % X_ALIGN;
schar *xp = (schar *) *xpp;
if(rndup)
rndup = X_ALIGN - rndup;
while(nelems-- != 0)
{
*tp++ = *xp++;
}
*xpp = (void *)(xp + rndup);
return ENOERR;
}
int
ncx_pad_getn_schar_longlong(const void **xpp, size_t nelems, longlong *tp)
{
size_t rndup = nelems % X_ALIGN;
schar *xp = (schar *) *xpp;
if(rndup)
rndup = X_ALIGN - rndup;
while(nelems-- != 0)
{
*tp++ = *xp++;
}
*xpp = (void *)(xp + rndup);
return ENOERR;
}
int
ncx_pad_getn_schar_ulonglong(const void **xpp, size_t nelems, ulonglong *tp)
{
size_t rndup = nelems % X_ALIGN;
schar *xp = (schar *) *xpp;
if(rndup)
rndup = X_ALIGN - rndup;
while(nelems-- != 0)
{
*tp++ = *xp++;
}
*xpp = (void *)(xp + rndup);
return ENOERR;
}
int
ncx_putn_schar_schar(void **xpp, size_t nelems, const schar *tp)
{
(void) memcpy(*xpp, tp, nelems);
*xpp = (void *)((char *)(*xpp) + nelems);
return ENOERR;
}
int
ncx_putn_schar_uchar(void **xpp, size_t nelems, const uchar *tp)
{
(void) memcpy(*xpp, tp, nelems);
*xpp = (void *)((char *)(*xpp) + nelems);
return ENOERR;
}
int
ncx_putn_schar_short(void **xpp, size_t nelems, const short *tp)
{
int status = ENOERR;
schar *xp = (schar *) *xpp;
while(nelems-- != 0)
{
if(*tp > X_SCHAR_MAX || *tp < X_SCHAR_MIN)
status = NC_ERANGE;
*xp++ = (schar) *tp++;
}
*xpp = (void *)xp;
return status;
}
int
ncx_putn_schar_int(void **xpp, size_t nelems, const int *tp)
{
int status = ENOERR;
schar *xp = (schar *) *xpp;
while(nelems-- != 0)
{
if(*tp > X_SCHAR_MAX || *tp < X_SCHAR_MIN)
status = NC_ERANGE;
*xp++ = (schar) *tp++;
}
*xpp = (void *)xp;
return status;
}
int
ncx_putn_schar_float(void **xpp, size_t nelems, const float *tp)
{
int status = ENOERR;
schar *xp = (schar *) *xpp;
while(nelems-- != 0)
{
if(*tp > X_SCHAR_MAX || *tp < X_SCHAR_MIN)
status = NC_ERANGE;
*xp++ = (schar) *tp++;
}
*xpp = (void *)xp;
return status;
}
int
ncx_putn_schar_double(void **xpp, size_t nelems, const double *tp)
{
int status = ENOERR;
schar *xp = (schar *) *xpp;
while(nelems-- != 0)
{
if(*tp > X_SCHAR_MAX || *tp < X_SCHAR_MIN)
status = NC_ERANGE;
*xp++ = (schar) *tp++;
}
*xpp = (void *)xp;
return status;
}
int
ncx_putn_schar_uint(void **xpp, size_t nelems, const uint *tp)
{
int status = ENOERR;
schar *xp = (schar *) *xpp;
while(nelems-- != 0)
{
if(*tp > X_SCHAR_MAX || *tp < X_SCHAR_MIN)
status = NC_ERANGE;
*xp++ = (schar) *tp++;
}
*xpp = (void *)xp;
return status;
}
int
ncx_putn_schar_longlong(void **xpp, size_t nelems, const longlong *tp)
{
int status = ENOERR;
schar *xp = (schar *) *xpp;
while(nelems-- != 0)
{
if(*tp > X_SCHAR_MAX || *tp < X_SCHAR_MIN)
status = NC_ERANGE;
*xp++ = (schar) *tp++;
}
*xpp = (void *)xp;
return status;
}
int
ncx_putn_schar_ulonglong(void **xpp, size_t nelems, const ulonglong *tp)
{
int status = ENOERR;
schar *xp = (schar *) *xpp;
while(nelems-- != 0)
{
if(*tp > X_SCHAR_MAX || *tp < X_SCHAR_MIN)
status = NC_ERANGE;
*xp++ = (schar) *tp++;
}
*xpp = (void *)xp;
return status;
}
int
ncx_pad_putn_schar_schar(void **xpp, size_t nelems, const schar *tp)
{
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;
}
int
ncx_pad_putn_schar_uchar(void **xpp, size_t nelems, const uchar *tp)
{
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;
}
int
ncx_pad_putn_schar_short(void **xpp, size_t nelems, const short *tp)
{
int status = ENOERR;
size_t rndup = nelems % X_ALIGN;
schar *xp = (schar *) *xpp;
if(rndup)
rndup = X_ALIGN - rndup;
while(nelems-- != 0)
{
/* N.B. schar as signed */
if(*tp > X_SCHAR_MAX || *tp < X_SCHAR_MIN)
status = NC_ERANGE;
*xp++ = (schar) *tp++;
}
if(rndup)
{
(void) memcpy(xp, nada, rndup);
xp += rndup;
}
*xpp = (void *)xp;
return status;
}
int
ncx_pad_putn_schar_int(void **xpp, size_t nelems, const int *tp)
{
int status = ENOERR;
size_t rndup = nelems % X_ALIGN;
schar *xp = (schar *) *xpp;
if(rndup)
rndup = X_ALIGN - rndup;
while(nelems-- != 0)
{
/* N.B. schar as signed */
if(*tp > X_SCHAR_MAX || *tp < X_SCHAR_MIN)
status = NC_ERANGE;
*xp++ = (schar) *tp++;
}
if(rndup)
{
(void) memcpy(xp, nada, rndup);
xp += rndup;
}
*xpp = (void *)xp;
return status;
}
int
ncx_pad_putn_schar_float(void **xpp, size_t nelems, const float *tp)
{
int status = ENOERR;
size_t rndup = nelems % X_ALIGN;
schar *xp = (schar *) *xpp;
if(rndup)
rndup = X_ALIGN - rndup;
while(nelems-- != 0)
{
/* N.B. schar as signed */
if(*tp > X_SCHAR_MAX || *tp < X_SCHAR_MIN)
status = NC_ERANGE;
*xp++ = (schar) *tp++;
}
if(rndup)
{
(void) memcpy(xp, nada, rndup);
xp += rndup;
}
*xpp = (void *)xp;
return status;
}
int
ncx_pad_putn_schar_double(void **xpp, size_t nelems, const double *tp)
{
int status = ENOERR;
size_t rndup = nelems % X_ALIGN;
schar *xp = (schar *) *xpp;
if(rndup)
rndup = X_ALIGN - rndup;
while(nelems-- != 0)
{
/* N.B. schar as signed */
if(*tp > X_SCHAR_MAX || *tp < X_SCHAR_MIN)
status = NC_ERANGE;
*xp++ = (schar) *tp++;
}
if(rndup)
{
(void) memcpy(xp, nada, rndup);
xp += rndup;
}
*xpp = (void *)xp;
return status;
}
int
ncx_pad_putn_schar_uint(void **xpp, size_t nelems, const uint *tp)
{
int status = ENOERR;
size_t rndup = nelems % X_ALIGN;
schar *xp = (schar *) *xpp;
if(rndup)
rndup = X_ALIGN - rndup;
while(nelems-- != 0)
{
/* N.B. schar as signed */
if(*tp > X_SCHAR_MAX || *tp < X_SCHAR_MIN)
status = NC_ERANGE;
*xp++ = (schar) *tp++;
}
if(rndup)
{
(void) memcpy(xp, nada, rndup);
xp += rndup;
}
*xpp = (void *)xp;
return status;
}
int
ncx_pad_putn_schar_longlong(void **xpp, size_t nelems, const longlong *tp)
{
int status = ENOERR;
size_t rndup = nelems % X_ALIGN;
schar *xp = (schar *) *xpp;
if(rndup)
rndup = X_ALIGN - rndup;
while(nelems-- != 0)
{
/* N.B. schar as signed */
if(*tp > X_SCHAR_MAX || *tp < X_SCHAR_MIN)
status = NC_ERANGE;
*xp++ = (schar) *tp++;
}
if(rndup)
{
(void) memcpy(xp, nada, rndup);
xp += rndup;
}
*xpp = (void *)xp;
return status;
}
int
ncx_pad_putn_schar_ulonglong(void **xpp, size_t nelems, const ulonglong *tp)
{
int status = ENOERR;
size_t rndup = nelems % X_ALIGN;
schar *xp = (schar *) *xpp;
if(rndup)
rndup = X_ALIGN - rndup;
while(nelems-- != 0)
{
/* N.B. schar as signed */
if(*tp > X_SCHAR_MAX || *tp < X_SCHAR_MIN)
status = NC_ERANGE;
*xp++ = (schar) *tp++;
}
if(rndup)
{
(void) memcpy(xp, nada, rndup);
xp += rndup;
}
*xpp = (void *)xp;
return status;
}
/* short */
int
ncx_getn_short_schar(const void **xpp, size_t nelems, schar *tp)
{
#if _SX && \
X_SIZEOF_SHORT == SIZEOF_SHORT
/* 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;
short tmp[LOOPCNT]; /* in case input is misaligned */
short *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) % SIZEOF_SHORT;
/* 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*SIZEOF_SHORT);
xp = tmp;
} else {
xp = (short *) *xpp;
}
/* copy the next block */
#pragma cdir loopcnt=LOOPCNT
#pragma cdir shortloop
for (i=0; i<ni; i++) {
tp[i] = (schar) Max( SCHAR_MIN, Min(SCHAR_MAX, (schar) xp[i]));
/* test for range errors (not always needed but do it anyway) */
nrange += xp[i] < SCHAR_MIN || xp[i] > SCHAR_MAX;
}
/* update xpp and tp */
if (realign) xp = (short *) *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 += X_SIZEOF_SHORT, tp++)
{
const int lstatus = ncx_get_short_schar(xp, tp);
if(lstatus != ENOERR)
status = lstatus;
}
*xpp = (const void *)xp;
return status;
# endif
}
int
ncx_getn_short_uchar(const void **xpp, size_t nelems, uchar *tp)
{
#if _SX && \
X_SIZEOF_SHORT == SIZEOF_SHORT
/* 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;
short tmp[LOOPCNT]; /* in case input is misaligned */
short *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) % SIZEOF_SHORT;
/* 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*SIZEOF_SHORT);
xp = tmp;
} else {
xp = (short *) *xpp;
}
/* copy the next block */
#pragma cdir loopcnt=LOOPCNT
#pragma cdir shortloop
for (i=0; i<ni; i++) {
tp[i] = (uchar) Max( UCHAR_MIN, Min(UCHAR_MAX, (uchar) xp[i]));
/* test for range errors (not always needed but do it anyway) */
nrange += xp[i] < UCHAR_MIN || xp[i] > UCHAR_MAX;
}
/* update xpp and tp */
if (realign) xp = (short *) *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 += X_SIZEOF_SHORT, tp++)
{
const int lstatus = ncx_get_short_uchar(xp, tp);
if(lstatus != ENOERR)
status = lstatus;
}
*xpp = (const void *)xp;
return status;
# endif
}
#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
int
ncx_getn_short_short(const void **xpp, size_t nelems, short *tp)
{
#if _SX && \
X_SIZEOF_SHORT == SIZEOF_SHORT
/* 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;
short tmp[LOOPCNT]; /* in case input is misaligned */
short *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) % SIZEOF_SHORT;
/* 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*SIZEOF_SHORT);
xp = tmp;
} else {
xp = (short *) *xpp;
}
/* copy the next block */
#pragma cdir loopcnt=LOOPCNT
#pragma cdir shortloop
for (i=0; i<ni; i++) {
tp[i] = (short) Max( SHORT_MIN, Min(SHORT_MAX, (short) xp[i]));
/* test for range errors (not always needed but do it anyway) */
nrange += xp[i] < SHORT_MIN || xp[i] > SHORT_MAX;
}
/* update xpp and tp */
if (realign) xp = (short *) *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 += X_SIZEOF_SHORT, tp++)
{
const int lstatus = ncx_get_short_short(xp, tp);
if(lstatus != ENOERR)
status = lstatus;
}
*xpp = (const void *)xp;
return status;
# endif
}
#endif
int
ncx_getn_short_int(const void **xpp, size_t nelems, int *tp)
{
#if _SX && \
X_SIZEOF_SHORT == SIZEOF_SHORT
/* 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;
short tmp[LOOPCNT]; /* in case input is misaligned */
short *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) % SIZEOF_SHORT;
/* 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*SIZEOF_SHORT);
xp = tmp;
} else {
xp = (short *) *xpp;
}
/* copy the next block */
#pragma cdir loopcnt=LOOPCNT
#pragma cdir shortloop
for (i=0; i<ni; i++) {
tp[i] = (int) Max( INT_MIN, Min(INT_MAX, (int) xp[i]));
/* test for range errors (not always needed but do it anyway) */
nrange += xp[i] < INT_MIN || xp[i] > INT_MAX;
}
/* update xpp and tp */
if (realign) xp = (short *) *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 += X_SIZEOF_SHORT, tp++)
{
const int lstatus = ncx_get_short_int(xp, tp);
if(lstatus != ENOERR)
status = lstatus;
}
*xpp = (const void *)xp;
return status;
# endif
}
int
ncx_getn_short_float(const void **xpp, size_t nelems, float *tp)
{
#if _SX && \
X_SIZEOF_SHORT == SIZEOF_SHORT
/* 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;
short tmp[LOOPCNT]; /* in case input is misaligned */
short *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) % SIZEOF_SHORT;
/* 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*SIZEOF_SHORT);
xp = tmp;
} else {
xp = (short *) *xpp;
}
/* copy the next block */
#pragma cdir loopcnt=LOOPCNT
#pragma cdir shortloop
for (i=0; i<ni; i++) {
tp[i] = (float) Max( FLOAT_MIN, Min(FLOAT_MAX, (float) xp[i]));
/* test for range errors (not always needed but do it anyway) */
nrange += xp[i] < FLOAT_MIN || xp[i] > FLOAT_MAX;
}
/* update xpp and tp */
if (realign) xp = (short *) *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 += X_SIZEOF_SHORT, tp++)
{
const int lstatus = ncx_get_short_float(xp, tp);
if(lstatus != ENOERR)
status = lstatus;
}
*xpp = (const void *)xp;
return status;
# endif
}
int
ncx_getn_short_double(const void **xpp, size_t nelems, double *tp)
{
#if _SX && \
X_SIZEOF_SHORT == SIZEOF_SHORT
/* 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;
short tmp[LOOPCNT]; /* in case input is misaligned */
short *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) % SIZEOF_SHORT;
/* 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*SIZEOF_SHORT);
xp = tmp;
} else {
xp = (short *) *xpp;
}
/* copy the next block */
#pragma cdir loopcnt=LOOPCNT
#pragma cdir shortloop
for (i=0; i<ni; i++) {
tp[i] = (double) Max( DOUBLE_MIN, Min(DOUBLE_MAX, (double) xp[i]));
/* test for range errors (not always needed but do it anyway) */
nrange += xp[i] < DOUBLE_MIN || xp[i] > DOUBLE_MAX;
}
/* update xpp and tp */
if (realign) xp = (short *) *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 += X_SIZEOF_SHORT, tp++)
{
const int lstatus = ncx_get_short_double(xp, tp);
if(lstatus != ENOERR)
status = lstatus;
}
*xpp = (const void *)xp;
return status;
# endif
}
int
ncx_getn_short_uint(const void **xpp, size_t nelems, uint *tp)
{
#if _SX && \
X_SIZEOF_SHORT == SIZEOF_SHORT
/* 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;
short tmp[LOOPCNT]; /* in case input is misaligned */
short *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) % SIZEOF_SHORT;
/* 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*SIZEOF_SHORT);
xp = tmp;
} else {
xp = (short *) *xpp;
}
/* copy the next block */
#pragma cdir loopcnt=LOOPCNT
#pragma cdir shortloop
for (i=0; i<ni; i++) {
tp[i] = (uint) Max( UINT_MIN, Min(UINT_MAX, (uint) xp[i]));
/* test for range errors (not always needed but do it anyway) */
nrange += xp[i] < UINT_MIN || xp[i] > UINT_MAX;
}
/* update xpp and tp */
if (realign) xp = (short *) *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 += X_SIZEOF_SHORT, tp++)
{
const int lstatus = ncx_get_short_uint(xp, tp);
if(lstatus != ENOERR)
status = lstatus;
}
*xpp = (const void *)xp;
return status;
# endif
}
int
ncx_getn_short_longlong(const void **xpp, size_t nelems, longlong *tp)
{
#if _SX && \
X_SIZEOF_SHORT == SIZEOF_SHORT
/* 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;
short tmp[LOOPCNT]; /* in case input is misaligned */
short *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) % SIZEOF_SHORT;
/* 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*SIZEOF_SHORT);
xp = tmp;
} else {
xp = (short *) *xpp;
}
/* copy the next block */
#pragma cdir loopcnt=LOOPCNT
#pragma cdir shortloop
for (i=0; i<ni; i++) {
tp[i] = (longlong) Max( LONGLONG_MIN, Min(LONGLONG_MAX, (longlong) xp[i]));
/* test for range errors (not always needed but do it anyway) */
nrange += xp[i] < LONGLONG_MIN || xp[i] > LONGLONG_MAX;
}
/* update xpp and tp */
if (realign) xp = (short *) *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 += X_SIZEOF_SHORT, tp++)
{
const int lstatus = ncx_get_short_longlong(xp, tp);
if(lstatus != ENOERR)
status = lstatus;
}
*xpp = (const void *)xp;
return status;
# endif
}
int
ncx_getn_short_ulonglong(const void **xpp, size_t nelems, ulonglong *tp)
{
#if _SX && \
X_SIZEOF_SHORT == SIZEOF_SHORT
/* 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;
short tmp[LOOPCNT]; /* in case input is misaligned */
short *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) % SIZEOF_SHORT;
/* 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*SIZEOF_SHORT);
xp = tmp;
} else {
xp = (short *) *xpp;
}
/* copy the next block */
#pragma cdir loopcnt=LOOPCNT
#pragma cdir shortloop
for (i=0; i<ni; i++) {
tp[i] = (ulonglong) Max( ULONGLONG_MIN, Min(ULONGLONG_MAX, (ulonglong) xp[i]));
/* test for range errors (not always needed but do it anyway) */
nrange += xp[i] < ULONGLONG_MIN || xp[i] > ULONGLONG_MAX;
}
/* update xpp and tp */
if (realign) xp = (short *) *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 += X_SIZEOF_SHORT, tp++)
{
const int lstatus = ncx_get_short_ulonglong(xp, tp);
if(lstatus != ENOERR)
status = lstatus;
}
*xpp = (const void *)xp;
return status;
# endif
}
int
ncx_pad_getn_short_schar(const void **xpp, size_t nelems, schar *tp)
{
const size_t rndup = nelems % 2;
const char *xp = (const char *) *xpp;
int status = ENOERR;
for( ; nelems != 0; nelems--, xp += X_SIZEOF_SHORT, tp++)
{
const int lstatus = ncx_get_short_schar(xp, tp);
if(lstatus != ENOERR)
status = lstatus;
}
if(rndup != 0)
xp += X_SIZEOF_SHORT;
*xpp = (void *)xp;
return status;
}
int
ncx_pad_getn_short_uchar(const void **xpp, size_t nelems, uchar *tp)
{
const size_t rndup = nelems % 2;
const char *xp = (const char *) *xpp;
int status = ENOERR;
for( ; nelems != 0; nelems--, xp += X_SIZEOF_SHORT, tp++)
{
const int lstatus = ncx_get_short_uchar(xp, tp);
if(lstatus != ENOERR)
status = lstatus;
}
if(rndup != 0)
xp += X_SIZEOF_SHORT;
*xpp = (void *)xp;
return status;
}
int
ncx_pad_getn_short_short(const void **xpp, size_t nelems, short *tp)
{
const size_t rndup = nelems % 2;
const char *xp = (const char *) *xpp;
int status = ENOERR;
for( ; nelems != 0; nelems--, xp += X_SIZEOF_SHORT, tp++)
{
const int lstatus = ncx_get_short_short(xp, tp);
if(lstatus != ENOERR)
status = lstatus;
}
if(rndup != 0)
xp += X_SIZEOF_SHORT;
*xpp = (void *)xp;
return status;
}
int
ncx_pad_getn_short_int(const void **xpp, size_t nelems, int *tp)
{
const size_t rndup = nelems % 2;
const char *xp = (const char *) *xpp;
int status = ENOERR;
for( ; nelems != 0; nelems--, xp += X_SIZEOF_SHORT, tp++)
{
const int lstatus = ncx_get_short_int(xp, tp);
if(lstatus != ENOERR)
status = lstatus;
}
if(rndup != 0)
xp += X_SIZEOF_SHORT;
*xpp = (void *)xp;
return status;
}
int
ncx_pad_getn_short_float(const void **xpp, size_t nelems, float *tp)
{
const size_t rndup = nelems % 2;
const char *xp = (const char *) *xpp;
int status = ENOERR;
for( ; nelems != 0; nelems--, xp += X_SIZEOF_SHORT, tp++)
{
const int lstatus = ncx_get_short_float(xp, tp);
if(lstatus != ENOERR)
status = lstatus;
}
if(rndup != 0)
xp += X_SIZEOF_SHORT;
*xpp = (void *)xp;
return status;
}
int
ncx_pad_getn_short_double(const void **xpp, size_t nelems, double *tp)
{
const size_t rndup = nelems % 2;
const char *xp = (const char *) *xpp;
int status = ENOERR;
for( ; nelems != 0; nelems--, xp += X_SIZEOF_SHORT, tp++)
{
const int lstatus = ncx_get_short_double(xp, tp);
if(lstatus != ENOERR)
status = lstatus;
}
if(rndup != 0)
xp += X_SIZEOF_SHORT;
*xpp = (void *)xp;
return status;
}
int
ncx_pad_getn_short_uint(const void **xpp, size_t nelems, uint *tp)
{
const size_t rndup = nelems % 2;
const char *xp = (const char *) *xpp;
int status = ENOERR;
for( ; nelems != 0; nelems--, xp += X_SIZEOF_SHORT, tp++)
{
const int lstatus = ncx_get_short_uint(xp, tp);
if(lstatus != ENOERR)
status = lstatus;
}
if(rndup != 0)
xp += X_SIZEOF_SHORT;
*xpp = (void *)xp;
return status;
}
int
ncx_pad_getn_short_longlong(const void **xpp, size_t nelems, longlong *tp)
{
const size_t rndup = nelems % 2;
const char *xp = (const char *) *xpp;
int status = ENOERR;
for( ; nelems != 0; nelems--, xp += X_SIZEOF_SHORT, tp++)
{
const int lstatus = ncx_get_short_longlong(xp, tp);
if(lstatus != ENOERR)
status = lstatus;
}
if(rndup != 0)
xp += X_SIZEOF_SHORT;
*xpp = (void *)xp;
return status;
}
int
ncx_pad_getn_short_ulonglong(const void **xpp, size_t nelems, ulonglong *tp)
{
const size_t rndup = nelems % 2;
const char *xp = (const char *) *xpp;
int status = ENOERR;
for( ; nelems != 0; nelems--, xp += X_SIZEOF_SHORT, tp++)
{
const int lstatus = ncx_get_short_ulonglong(xp, tp);
if(lstatus != ENOERR)
status = lstatus;
}
if(rndup != 0)
xp += X_SIZEOF_SHORT;
*xpp = (void *)xp;
return status;
}
int
ncx_putn_short_schar(void **xpp, size_t nelems, const schar *tp)
{
#if _SX && \
X_SIZEOF_SHORT == SIZEOF_SHORT
/* 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;
short tmp[LOOPCNT]; /* in case input is misaligned */
short *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) % SIZEOF_SHORT;
/* 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 = (short *) *xpp;
}
/* copy the next block */
#pragma cdir loopcnt=LOOPCNT
#pragma cdir shortloop
for (i=0; i<ni; i++) {
/* the normal case: */
xp[i] = (short) Max( X_SHORT_MIN, Min(X_SHORT_MAX, (short) tp[i]));
/* test for range errors (not always needed but do it anyway) */
nrange += tp[i] < X_SHORT_MIN || tp[i] > X_SHORT_MAX;
}
/* copy workspace back if necessary */
if (realign) {
memcpy(*xpp, tmp, ni*X_SIZEOF_SHORT);
xp = (short *) *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 += X_SIZEOF_SHORT, tp++)
{
int lstatus = ncx_put_short_schar(xp, tp);
if(lstatus != ENOERR)
status = lstatus;
}
*xpp = (void *)xp;
return status;
#endif
}
int
ncx_putn_short_uchar(void **xpp, size_t nelems, const uchar *tp)
{
#if _SX && \
X_SIZEOF_SHORT == SIZEOF_SHORT
/* 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;
short tmp[LOOPCNT]; /* in case input is misaligned */
short *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) % SIZEOF_SHORT;
/* 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 = (short *) *xpp;
}
/* copy the next block */
#pragma cdir loopcnt=LOOPCNT
#pragma cdir shortloop
for (i=0; i<ni; i++) {
/* the normal case: */
xp[i] = (short) Max( X_SHORT_MIN, Min(X_SHORT_MAX, (short) tp[i]));
/* test for range errors (not always needed but do it anyway) */
nrange += tp[i] < X_SHORT_MIN || tp[i] > X_SHORT_MAX;
}
/* copy workspace back if necessary */
if (realign) {
memcpy(*xpp, tmp, ni*X_SIZEOF_SHORT);
xp = (short *) *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 += X_SIZEOF_SHORT, tp++)
{
int lstatus = ncx_put_short_uchar(xp, tp);
if(lstatus != ENOERR)
status = lstatus;
}
*xpp = (void *)xp;
return status;
#endif
}
#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
int
ncx_putn_short_short(void **xpp, size_t nelems, const short *tp)
{
#if _SX && \
X_SIZEOF_SHORT == SIZEOF_SHORT
/* 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;
short tmp[LOOPCNT]; /* in case input is misaligned */
short *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) % SIZEOF_SHORT;
/* 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 = (short *) *xpp;
}
/* copy the next block */
#pragma cdir loopcnt=LOOPCNT
#pragma cdir shortloop
for (i=0; i<ni; i++) {
/* the normal case: */
xp[i] = (short) Max( X_SHORT_MIN, Min(X_SHORT_MAX, (short) tp[i]));
/* test for range errors (not always needed but do it anyway) */
nrange += tp[i] < X_SHORT_MIN || tp[i] > X_SHORT_MAX;
}
/* copy workspace back if necessary */
if (realign) {
memcpy(*xpp, tmp, ni*X_SIZEOF_SHORT);
xp = (short *) *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 += X_SIZEOF_SHORT, tp++)
{
int lstatus = ncx_put_short_short(xp, tp);
if(lstatus != ENOERR)
status = lstatus;
}
*xpp = (void *)xp;
return status;
#endif
}
#endif
int
ncx_putn_short_int(void **xpp, size_t nelems, const int *tp)
{
#if _SX && \
X_SIZEOF_SHORT == SIZEOF_SHORT
/* 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;
short tmp[LOOPCNT]; /* in case input is misaligned */
short *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) % SIZEOF_SHORT;
/* 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 = (short *) *xpp;
}
/* copy the next block */
#pragma cdir loopcnt=LOOPCNT
#pragma cdir shortloop
for (i=0; i<ni; i++) {
/* the normal case: */
xp[i] = (short) Max( X_SHORT_MIN, Min(X_SHORT_MAX, (short) tp[i]));
/* test for range errors (not always needed but do it anyway) */
nrange += tp[i] < X_SHORT_MIN || tp[i] > X_SHORT_MAX;
}
/* copy workspace back if necessary */
if (realign) {
memcpy(*xpp, tmp, ni*X_SIZEOF_SHORT);
xp = (short *) *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 += X_SIZEOF_SHORT, tp++)
{
int lstatus = ncx_put_short_int(xp, tp);
if(lstatus != ENOERR)
status = lstatus;
}
*xpp = (void *)xp;
return status;
#endif
}
int
ncx_putn_short_float(void **xpp, size_t nelems, const float *tp)
{
#if _SX && \
X_SIZEOF_SHORT == SIZEOF_SHORT
/* 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;
short tmp[LOOPCNT]; /* in case input is misaligned */
short *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) % SIZEOF_SHORT;
/* 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 = (short *) *xpp;
}
/* copy the next block */
#pragma cdir loopcnt=LOOPCNT
#pragma cdir shortloop
for (i=0; i<ni; i++) {
/* the normal case: */
xp[i] = (short) Max( X_SHORT_MIN, Min(X_SHORT_MAX, (short) tp[i]));
/* test for range errors (not always needed but do it anyway) */
nrange += tp[i] < X_SHORT_MIN || tp[i] > X_SHORT_MAX;
}
/* copy workspace back if necessary */
if (realign) {
memcpy(*xpp, tmp, ni*X_SIZEOF_SHORT);
xp = (short *) *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 += X_SIZEOF_SHORT, tp++)
{
int lstatus = ncx_put_short_float(xp, tp);
if(lstatus != ENOERR)
status = lstatus;
}
*xpp = (void *)xp;
return status;
#endif
}
int
ncx_putn_short_double(void **xpp, size_t nelems, const double *tp)
{
#if _SX && \
X_SIZEOF_SHORT == SIZEOF_SHORT
/* 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;
short tmp[LOOPCNT]; /* in case input is misaligned */
short *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) % SIZEOF_SHORT;
/* 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 = (short *) *xpp;
}
/* copy the next block */
#pragma cdir loopcnt=LOOPCNT
#pragma cdir shortloop
for (i=0; i<ni; i++) {
/* the normal case: */
xp[i] = (short) Max( X_SHORT_MIN, Min(X_SHORT_MAX, (short) tp[i]));
/* test for range errors (not always needed but do it anyway) */
nrange += tp[i] < X_SHORT_MIN || tp[i] > X_SHORT_MAX;
}
/* copy workspace back if necessary */
if (realign) {
memcpy(*xpp, tmp, ni*X_SIZEOF_SHORT);
xp = (short *) *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 += X_SIZEOF_SHORT, tp++)
{
int lstatus = ncx_put_short_double(xp, tp);
if(lstatus != ENOERR)
status = lstatus;
}
*xpp = (void *)xp;
return status;
#endif
}
int
ncx_putn_short_uint(void **xpp, size_t nelems, const uint *tp)
{
#if _SX && \
X_SIZEOF_SHORT == SIZEOF_SHORT
/* 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;
short tmp[LOOPCNT]; /* in case input is misaligned */
short *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) % SIZEOF_SHORT;
/* 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 = (short *) *xpp;
}
/* copy the next block */
#pragma cdir loopcnt=LOOPCNT
#pragma cdir shortloop
for (i=0; i<ni; i++) {
/* the normal case: */
xp[i] = (short) Max( X_SHORT_MIN, Min(X_SHORT_MAX, (short) tp[i]));
/* test for range errors (not always needed but do it anyway) */
nrange += tp[i] < X_SHORT_MIN || tp[i] > X_SHORT_MAX;
}
/* copy workspace back if necessary */
if (realign) {
memcpy(*xpp, tmp, ni*X_SIZEOF_SHORT);
xp = (short *) *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 += X_SIZEOF_SHORT, tp++)
{
int lstatus = ncx_put_short_uint(xp, tp);
if(lstatus != ENOERR)
status = lstatus;
}
*xpp = (void *)xp;
return status;
#endif
}
int
ncx_putn_short_longlong(void **xpp, size_t nelems, const longlong *tp)
{
#if _SX && \
X_SIZEOF_SHORT == SIZEOF_SHORT
/* 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;
short tmp[LOOPCNT]; /* in case input is misaligned */
short *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) % SIZEOF_SHORT;
/* 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 = (short *) *xpp;
}
/* copy the next block */
#pragma cdir loopcnt=LOOPCNT
#pragma cdir shortloop
for (i=0; i<ni; i++) {
/* the normal case: */
xp[i] = (short) Max( X_SHORT_MIN, Min(X_SHORT_MAX, (short) tp[i]));
/* test for range errors (not always needed but do it anyway) */
nrange += tp[i] < X_SHORT_MIN || tp[i] > X_SHORT_MAX;
}
/* copy workspace back if necessary */
if (realign) {
memcpy(*xpp, tmp, ni*X_SIZEOF_SHORT);
xp = (short *) *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 += X_SIZEOF_SHORT, tp++)
{
int lstatus = ncx_put_short_longlong(xp, tp);
if(lstatus != ENOERR)
status = lstatus;
}
*xpp = (void *)xp;
return status;
#endif
}
int
ncx_putn_short_ulonglong(void **xpp, size_t nelems, const ulonglong *tp)
{
#if _SX && \
X_SIZEOF_SHORT == SIZEOF_SHORT
/* 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;
short tmp[LOOPCNT]; /* in case input is misaligned */
short *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) % SIZEOF_SHORT;
/* 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 = (short *) *xpp;
}
/* copy the next block */
#pragma cdir loopcnt=LOOPCNT
#pragma cdir shortloop
for (i=0; i<ni; i++) {
/* the normal case: */
xp[i] = (short) Max( X_SHORT_MIN, Min(X_SHORT_MAX, (short) tp[i]));
/* test for range errors (not always needed but do it anyway) */
nrange += tp[i] < X_SHORT_MIN || tp[i] > X_SHORT_MAX;
}
/* copy workspace back if necessary */
if (realign) {
memcpy(*xpp, tmp, ni*X_SIZEOF_SHORT);
xp = (short *) *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 += X_SIZEOF_SHORT, tp++)
{
int lstatus = ncx_put_short_ulonglong(xp, tp);
if(lstatus != ENOERR)
status = lstatus;
}
*xpp = (void *)xp;
return status;
#endif
}
int
ncx_pad_putn_short_schar(void **xpp, size_t nelems, const schar *tp)
{
const size_t rndup = nelems % 2;
char *xp = (char *) *xpp;
int status = ENOERR;
for( ; nelems != 0; nelems--, xp += X_SIZEOF_SHORT, tp++)
{
int lstatus = ncx_put_short_schar(xp, tp);
if(lstatus != ENOERR)
status = lstatus;
}
if(rndup != 0)
{
(void) memcpy(xp, nada, X_SIZEOF_SHORT);
xp += X_SIZEOF_SHORT;
}
*xpp = (void *)xp;
return status;
}
int
ncx_pad_putn_short_uchar(void **xpp, size_t nelems, const uchar *tp)
{
const size_t rndup = nelems % 2;
char *xp = (char *) *xpp;
int status = ENOERR;
for( ; nelems != 0; nelems--, xp += X_SIZEOF_SHORT, tp++)
{
int lstatus = ncx_put_short_uchar(xp, tp);
if(lstatus != ENOERR)
status = lstatus;
}
if(rndup != 0)
{
(void) memcpy(xp, nada, X_SIZEOF_SHORT);
xp += X_SIZEOF_SHORT;
}
*xpp = (void *)xp;
return status;
}
int
ncx_pad_putn_short_short(void **xpp, size_t nelems, const short *tp)
{
const size_t rndup = nelems % 2;
char *xp = (char *) *xpp;
int status = ENOERR;
for( ; nelems != 0; nelems--, xp += X_SIZEOF_SHORT, tp++)
{
int lstatus = ncx_put_short_short(xp, tp);
if(lstatus != ENOERR)
status = lstatus;
}
if(rndup != 0)
{
(void) memcpy(xp, nada, X_SIZEOF_SHORT);
xp += X_SIZEOF_SHORT;
}
*xpp = (void *)xp;
return status;
}
int
ncx_pad_putn_short_int(void **xpp, size_t nelems, const int *tp)
{
const size_t rndup = nelems % 2;
char *xp = (char *) *xpp;
int status = ENOERR;
for( ; nelems != 0; nelems--, xp += X_SIZEOF_SHORT, tp++)
{
int lstatus = ncx_put_short_int(xp, tp);
if(lstatus != ENOERR)
status = lstatus;
}
if(rndup != 0)
{
(void) memcpy(xp, nada, X_SIZEOF_SHORT);
xp += X_SIZEOF_SHORT;
}
*xpp = (void *)xp;
return status;
}
int
ncx_pad_putn_short_float(void **xpp, size_t nelems, const float *tp)
{
const size_t rndup = nelems % 2;
char *xp = (char *) *xpp;
int status = ENOERR;
for( ; nelems != 0; nelems--, xp += X_SIZEOF_SHORT, tp++)
{
int lstatus = ncx_put_short_float(xp, tp);
if(lstatus != ENOERR)
status = lstatus;
}
if(rndup != 0)
{
(void) memcpy(xp, nada, X_SIZEOF_SHORT);
xp += X_SIZEOF_SHORT;
}
*xpp = (void *)xp;
return status;
}
int
ncx_pad_putn_short_double(void **xpp, size_t nelems, const double *tp)
{
const size_t rndup = nelems % 2;
char *xp = (char *) *xpp;
int status = ENOERR;
for( ; nelems != 0; nelems--, xp += X_SIZEOF_SHORT, tp++)
{
int lstatus = ncx_put_short_double(xp, tp);
if(lstatus != ENOERR)
status = lstatus;
}
if(rndup != 0)
{
(void) memcpy(xp, nada, X_SIZEOF_SHORT);
xp += X_SIZEOF_SHORT;
}
*xpp = (void *)xp;
return status;
}
int
ncx_pad_putn_short_uint(void **xpp, size_t nelems, const uint *tp)
{
const size_t rndup = nelems % 2;
char *xp = (char *) *xpp;
int status = ENOERR;
for( ; nelems != 0; nelems--, xp += X_SIZEOF_SHORT, tp++)
{
int lstatus = ncx_put_short_uint(xp, tp);
if(lstatus != ENOERR)
status = lstatus;
}
if(rndup != 0)
{
(void) memcpy(xp, nada, X_SIZEOF_SHORT);
xp += X_SIZEOF_SHORT;
}
*xpp = (void *)xp;
return status;
}
int
ncx_pad_putn_short_longlong(void **xpp, size_t nelems, const longlong *tp)
{
const size_t rndup = nelems % 2;
char *xp = (char *) *xpp;
int status = ENOERR;
for( ; nelems != 0; nelems--, xp += X_SIZEOF_SHORT, tp++)
{
int lstatus = ncx_put_short_longlong(xp, tp);
if(lstatus != ENOERR)
status = lstatus;
}
if(rndup != 0)
{
(void) memcpy(xp, nada, X_SIZEOF_SHORT);
xp += X_SIZEOF_SHORT;
}
*xpp = (void *)xp;
return status;
}
int
ncx_pad_putn_short_ulonglong(void **xpp, size_t nelems, const ulonglong *tp)
{
const size_t rndup = nelems % 2;
char *xp = (char *) *xpp;
int status = ENOERR;
for( ; nelems != 0; nelems--, xp += X_SIZEOF_SHORT, tp++)
{
int lstatus = ncx_put_short_ulonglong(xp, tp);
if(lstatus != ENOERR)
status = lstatus;
}
if(rndup != 0)
{
(void) memcpy(xp, nada, X_SIZEOF_SHORT);
xp += X_SIZEOF_SHORT;
}
*xpp = (void *)xp;
return status;
}
/* int */
int
ncx_getn_int_schar(const void **xpp, size_t nelems, schar *tp)
{
#if _SX && \
X_SIZEOF_INT == SIZEOF_INT
/* 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;
int tmp[LOOPCNT]; /* in case input is misaligned */
int *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) % SIZEOF_INT;
/* 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*SIZEOF_INT);
xp = tmp;
} else {
xp = (int *) *xpp;
}
/* copy the next block */
#pragma cdir loopcnt=LOOPCNT
#pragma cdir shortloop
for (i=0; i<ni; i++) {
tp[i] = (schar) Max( SCHAR_MIN, Min(SCHAR_MAX, (schar) xp[i]));
/* test for range errors (not always needed but do it anyway) */
nrange += xp[i] < SCHAR_MIN || xp[i] > SCHAR_MAX;
}
/* update xpp and tp */
if (realign) xp = (int *) *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 += X_SIZEOF_INT, tp++)
{
const int lstatus = ncx_get_int_schar(xp, tp);
if(lstatus != ENOERR)
status = lstatus;
}
*xpp = (const void *)xp;
return status;
# endif
}
int
ncx_getn_int_uchar(const void **xpp, size_t nelems, uchar *tp)
{
#if _SX && \
X_SIZEOF_INT == SIZEOF_INT
/* 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;
int tmp[LOOPCNT]; /* in case input is misaligned */
int *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) % SIZEOF_INT;
/* 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*SIZEOF_INT);
xp = tmp;
} else {
xp = (int *) *xpp;
}
/* copy the next block */
#pragma cdir loopcnt=LOOPCNT
#pragma cdir shortloop
for (i=0; i<ni; i++) {
tp[i] = (uchar) Max( UCHAR_MIN, Min(UCHAR_MAX, (uchar) xp[i]));
/* test for range errors (not always needed but do it anyway) */
nrange += xp[i] < UCHAR_MIN || xp[i] > UCHAR_MAX;
}
/* update xpp and tp */
if (realign) xp = (int *) *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 += X_SIZEOF_INT, tp++)
{
const int lstatus = ncx_get_int_uchar(xp, tp);
if(lstatus != ENOERR)
status = lstatus;
}
*xpp = (const void *)xp;
return status;
# endif
}
int
ncx_getn_int_short(const void **xpp, size_t nelems, short *tp)
{
#if _SX && \
X_SIZEOF_INT == SIZEOF_INT
/* 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;
int tmp[LOOPCNT]; /* in case input is misaligned */
int *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) % SIZEOF_INT;
/* 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*SIZEOF_INT);
xp = tmp;
} else {
xp = (int *) *xpp;
}
/* copy the next block */
#pragma cdir loopcnt=LOOPCNT
#pragma cdir shortloop
for (i=0; i<ni; i++) {
tp[i] = (short) Max( SHORT_MIN, Min(SHORT_MAX, (short) xp[i]));
/* test for range errors (not always needed but do it anyway) */
nrange += xp[i] < SHORT_MIN || xp[i] > SHORT_MAX;
}
/* update xpp and tp */
if (realign) xp = (int *) *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 += X_SIZEOF_INT, tp++)
{
const int lstatus = ncx_get_int_short(xp, tp);
if(lstatus != ENOERR)
status = lstatus;
}
*xpp = (const void *)xp;
return status;
# endif
}
#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;
}
int
ncx_getn_int_uint(const void **xpp, size_t nelems, unsigned 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
int
ncx_getn_int_int(const void **xpp, size_t nelems, int *tp)
{
#if _SX && \
X_SIZEOF_INT == SIZEOF_INT
/* 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;
int tmp[LOOPCNT]; /* in case input is misaligned */
int *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) % SIZEOF_INT;
/* 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*SIZEOF_INT);
xp = tmp;
} else {
xp = (int *) *xpp;
}
/* copy the next block */
#pragma cdir loopcnt=LOOPCNT
#pragma cdir shortloop
for (i=0; i<ni; i++) {
tp[i] = (int) Max( INT_MIN, Min(INT_MAX, (int) xp[i]));
/* test for range errors (not always needed but do it anyway) */
nrange += xp[i] < INT_MIN || xp[i] > INT_MAX;
}
/* update xpp and tp */
if (realign) xp = (int *) *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 += X_SIZEOF_INT, tp++)
{
const int lstatus = ncx_get_int_int(xp, tp);
if(lstatus != ENOERR)
status = lstatus;
}
*xpp = (const void *)xp;
return status;
# endif
}
int
ncx_getn_int_uint(const void **xpp, size_t nelems, uint *tp)
{
#if _SX && \
X_SIZEOF_INT == SIZEOF_INT
/* 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;
int tmp[LOOPCNT]; /* in case input is misaligned */
int *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) % SIZEOF_INT;
/* 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*SIZEOF_INT);
xp = tmp;
} else {
xp = (int *) *xpp;
}
/* copy the next block */
#pragma cdir loopcnt=LOOPCNT
#pragma cdir shortloop
for (i=0; i<ni; i++) {
tp[i] = (uint) Max( UINT_MIN, Min(UINT_MAX, (uint) xp[i]));
/* test for range errors (not always needed but do it anyway) */
nrange += xp[i] < UINT_MIN || xp[i] > UINT_MAX;
}
/* update xpp and tp */
if (realign) xp = (int *) *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 += X_SIZEOF_INT, tp++)
{
const int lstatus = ncx_get_int_uint(xp, tp);
if(lstatus != ENOERR)
status = lstatus;
}
*xpp = (const void *)xp;
return status;
# endif
}
#endif
int
ncx_getn_int_longlong(const void **xpp, size_t nelems, longlong *tp)
{
#if _SX && \
X_SIZEOF_INT == SIZEOF_INT
/* 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;
int tmp[LOOPCNT]; /* in case input is misaligned */
int *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) % SIZEOF_INT;
/* 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*SIZEOF_INT);
xp = tmp;
} else {
xp = (int *) *xpp;
}
/* copy the next block */
#pragma cdir loopcnt=LOOPCNT
#pragma cdir shortloop
for (i=0; i<ni; i++) {
tp[i] = (longlong) Max( LONGLONG_MIN, Min(LONGLONG_MAX, (longlong) xp[i]));
/* test for range errors (not always needed but do it anyway) */
nrange += xp[i] < LONGLONG_MIN || xp[i] > LONGLONG_MAX;
}
/* update xpp and tp */
if (realign) xp = (int *) *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 += X_SIZEOF_INT, tp++)
{
const int lstatus = ncx_get_int_longlong(xp, tp);
if(lstatus != ENOERR)
status = lstatus;
}
*xpp = (const void *)xp;
return status;
# endif
}
int
ncx_getn_int_ulonglong(const void **xpp, size_t nelems, ulonglong *tp)
{
#if _SX && \
X_SIZEOF_INT == SIZEOF_INT
/* 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;
int tmp[LOOPCNT]; /* in case input is misaligned */
int *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) % SIZEOF_INT;
/* 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*SIZEOF_INT);
xp = tmp;
} else {
xp = (int *) *xpp;
}
/* copy the next block */
#pragma cdir loopcnt=LOOPCNT
#pragma cdir shortloop
for (i=0; i<ni; i++) {
tp[i] = (ulonglong) Max( ULONGLONG_MIN, Min(ULONGLONG_MAX, (ulonglong) xp[i]));
/* test for range errors (not always needed but do it anyway) */
nrange += xp[i] < ULONGLONG_MIN || xp[i] > ULONGLONG_MAX;
}
/* update xpp and tp */
if (realign) xp = (int *) *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 += X_SIZEOF_INT, tp++)
{
const int lstatus = ncx_get_int_ulonglong(xp, tp);
if(lstatus != ENOERR)
status = lstatus;
}
*xpp = (const void *)xp;
return status;
# endif
}
int
ncx_getn_int_float(const void **xpp, size_t nelems, float *tp)
{
#if _SX && \
X_SIZEOF_INT == SIZEOF_INT
/* 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;
int tmp[LOOPCNT]; /* in case input is misaligned */
int *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) % SIZEOF_INT;
/* 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*SIZEOF_INT);
xp = tmp;
} else {
xp = (int *) *xpp;
}
/* copy the next block */
#pragma cdir loopcnt=LOOPCNT
#pragma cdir shortloop
for (i=0; i<ni; i++) {
tp[i] = (float) Max( FLOAT_MIN, Min(FLOAT_MAX, (float) xp[i]));
/* test for range errors (not always needed but do it anyway) */
nrange += xp[i] < FLOAT_MIN || xp[i] > FLOAT_MAX;
}
/* update xpp and tp */
if (realign) xp = (int *) *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 += X_SIZEOF_INT, tp++)
{
const int lstatus = ncx_get_int_float(xp, tp);
if(lstatus != ENOERR)
status = lstatus;
}
*xpp = (const void *)xp;
return status;
# endif
}
int
ncx_getn_int_double(const void **xpp, size_t nelems, double *tp)
{
#if _SX && \
X_SIZEOF_INT == SIZEOF_INT
/* 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;
int tmp[LOOPCNT]; /* in case input is misaligned */
int *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) % SIZEOF_INT;
/* 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*SIZEOF_INT);
xp = tmp;
} else {
xp = (int *) *xpp;
}
/* copy the next block */
#pragma cdir loopcnt=LOOPCNT
#pragma cdir shortloop
for (i=0; i<ni; i++) {
tp[i] = (double) Max( DOUBLE_MIN, Min(DOUBLE_MAX, (double) xp[i]));
/* test for range errors (not always needed but do it anyway) */
nrange += xp[i] < DOUBLE_MIN || xp[i] > DOUBLE_MAX;
}
/* update xpp and tp */
if (realign) xp = (int *) *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 += X_SIZEOF_INT, tp++)
{
const int lstatus = ncx_get_int_double(xp, tp);
if(lstatus != ENOERR)
status = lstatus;
}
*xpp = (const void *)xp;
return status;
# endif
}
int
ncx_putn_int_schar(void **xpp, size_t nelems, const schar *tp)
{
#if _SX && \
X_SIZEOF_INT == SIZEOF_INT
/* 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;
int tmp[LOOPCNT]; /* in case input is misaligned */
int *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) % SIZEOF_INT;
/* 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 = (int *) *xpp;
}
/* copy the next block */
#pragma cdir loopcnt=LOOPCNT
#pragma cdir shortloop
for (i=0; i<ni; i++) {
/* the normal case: */
xp[i] = (int) Max( X_INT_MIN, Min(X_INT_MAX, (int) tp[i]));
/* test for range errors (not always needed but do it anyway) */
nrange += tp[i] < X_INT_MIN || tp[i] > X_INT_MAX;
}
/* copy workspace back if necessary */
if (realign) {
memcpy(*xpp, tmp, ni*X_SIZEOF_INT);
xp = (int *) *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 += X_SIZEOF_INT, tp++)
{
int lstatus = ncx_put_int_schar(xp, tp);
if(lstatus != ENOERR)
status = lstatus;
}
*xpp = (void *)xp;
return status;
#endif
}
int
ncx_putn_int_uchar(void **xpp, size_t nelems, const uchar *tp)
{
#if _SX && \
X_SIZEOF_INT == SIZEOF_INT
/* 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;
int tmp[LOOPCNT]; /* in case input is misaligned */
int *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) % SIZEOF_INT;
/* 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 = (int *) *xpp;
}
/* copy the next block */
#pragma cdir loopcnt=LOOPCNT
#pragma cdir shortloop
for (i=0; i<ni; i++) {
/* the normal case: */
xp[i] = (int) Max( X_INT_MIN, Min(X_INT_MAX, (int) tp[i]));
/* test for range errors (not always needed but do it anyway) */
nrange += tp[i] < X_INT_MIN || tp[i] > X_INT_MAX;
}
/* copy workspace back if necessary */
if (realign) {
memcpy(*xpp, tmp, ni*X_SIZEOF_INT);
xp = (int *) *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 += X_SIZEOF_INT, tp++)
{
int lstatus = ncx_put_int_uchar(xp, tp);
if(lstatus != ENOERR)
status = lstatus;
}
*xpp = (void *)xp;
return status;
#endif
}
int
ncx_putn_int_short(void **xpp, size_t nelems, const short *tp)
{
#if _SX && \
X_SIZEOF_INT == SIZEOF_INT
/* 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;
int tmp[LOOPCNT]; /* in case input is misaligned */
int *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) % SIZEOF_INT;
/* 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 = (int *) *xpp;
}
/* copy the next block */
#pragma cdir loopcnt=LOOPCNT
#pragma cdir shortloop
for (i=0; i<ni; i++) {
/* the normal case: */
xp[i] = (int) Max( X_INT_MIN, Min(X_INT_MAX, (int) tp[i]));
/* test for range errors (not always needed but do it anyway) */
nrange += tp[i] < X_INT_MIN || tp[i] > X_INT_MAX;
}
/* copy workspace back if necessary */
if (realign) {
memcpy(*xpp, tmp, ni*X_SIZEOF_INT);
xp = (int *) *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 += X_SIZEOF_INT, tp++)
{
int lstatus = ncx_put_int_short(xp, tp);
if(lstatus != ENOERR)
status = lstatus;
}
*xpp = (void *)xp;
return status;
#endif
}
#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;
}
int
ncx_putn_int_uint(void **xpp, size_t nelems, const unsigned 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
int
ncx_putn_int_int(void **xpp, size_t nelems, const int *tp)
{
#if _SX && \
X_SIZEOF_INT == SIZEOF_INT
/* 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;
int tmp[LOOPCNT]; /* in case input is misaligned */
int *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) % SIZEOF_INT;
/* 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 = (int *) *xpp;
}
/* copy the next block */
#pragma cdir loopcnt=LOOPCNT
#pragma cdir shortloop
for (i=0; i<ni; i++) {
/* the normal case: */
xp[i] = (int) Max( X_INT_MIN, Min(X_INT_MAX, (int) tp[i]));
/* test for range errors (not always needed but do it anyway) */
nrange += tp[i] < X_INT_MIN || tp[i] > X_INT_MAX;
}
/* copy workspace back if necessary */
if (realign) {
memcpy(*xpp, tmp, ni*X_SIZEOF_INT);
xp = (int *) *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 += X_SIZEOF_INT, tp++)
{
int lstatus = ncx_put_int_int(xp, tp);
if(lstatus != ENOERR)
status = lstatus;
}
*xpp = (void *)xp;
return status;
#endif
}
int
ncx_putn_int_uint(void **xpp, size_t nelems, const uint *tp)
{
#if _SX && \
X_SIZEOF_INT == SIZEOF_INT
/* 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;
int tmp[LOOPCNT]; /* in case input is misaligned */
int *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) % SIZEOF_INT;
/* 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 = (int *) *xpp;
}
/* copy the next block */
#pragma cdir loopcnt=LOOPCNT
#pragma cdir shortloop
for (i=0; i<ni; i++) {
/* the normal case: */
xp[i] = (int) Max( X_INT_MIN, Min(X_INT_MAX, (int) tp[i]));
/* test for range errors (not always needed but do it anyway) */
nrange += tp[i] < X_INT_MIN || tp[i] > X_INT_MAX;
}
/* copy workspace back if necessary */
if (realign) {
memcpy(*xpp, tmp, ni*X_SIZEOF_INT);
xp = (int *) *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 += X_SIZEOF_INT, tp++)
{
int lstatus = ncx_put_int_uint(xp, tp);
if(lstatus != ENOERR)
status = lstatus;
}
*xpp = (void *)xp;
return status;
#endif
}
#endif
int
ncx_putn_int_longlong(void **xpp, size_t nelems, const longlong *tp)
{
#if _SX && \
X_SIZEOF_INT == SIZEOF_INT
/* 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;
int tmp[LOOPCNT]; /* in case input is misaligned */
int *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) % SIZEOF_INT;
/* 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 = (int *) *xpp;
}
/* copy the next block */
#pragma cdir loopcnt=LOOPCNT
#pragma cdir shortloop
for (i=0; i<ni; i++) {
/* the normal case: */
xp[i] = (int) Max( X_INT_MIN, Min(X_INT_MAX, (int) tp[i]));
/* test for range errors (not always needed but do it anyway) */
nrange += tp[i] < X_INT_MIN || tp[i] > X_INT_MAX;
}
/* copy workspace back if necessary */
if (realign) {
memcpy(*xpp, tmp, ni*X_SIZEOF_INT);
xp = (int *) *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 += X_SIZEOF_INT, tp++)
{
int lstatus = ncx_put_int_longlong(xp, tp);
if(lstatus != ENOERR)
status = lstatus;
}
*xpp = (void *)xp;
return status;
#endif
}
int
ncx_putn_int_ulonglong(void **xpp, size_t nelems, const ulonglong *tp)
{
#if _SX && \
X_SIZEOF_INT == SIZEOF_INT
/* 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;
int tmp[LOOPCNT]; /* in case input is misaligned */
int *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) % SIZEOF_INT;
/* 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 = (int *) *xpp;
}
/* copy the next block */
#pragma cdir loopcnt=LOOPCNT
#pragma cdir shortloop
for (i=0; i<ni; i++) {
/* the normal case: */
xp[i] = (int) Max( X_INT_MIN, Min(X_INT_MAX, (int) tp[i]));
/* test for range errors (not always needed but do it anyway) */
nrange += tp[i] < X_INT_MIN || tp[i] > X_INT_MAX;
}
/* copy workspace back if necessary */
if (realign) {
memcpy(*xpp, tmp, ni*X_SIZEOF_INT);
xp = (int *) *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 += X_SIZEOF_INT, tp++)
{
int lstatus = ncx_put_int_ulonglong(xp, tp);
if(lstatus != ENOERR)
status = lstatus;
}
*xpp = (void *)xp;
return status;
#endif
}
int
ncx_putn_int_float(void **xpp, size_t nelems, const float *tp)
{
#if _SX && \
X_SIZEOF_INT == SIZEOF_INT
/* 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;
int tmp[LOOPCNT]; /* in case input is misaligned */
int *xp;
double d; /* special case for ncx_putn_int_float */
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) % SIZEOF_INT;
/* 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 = (int *) *xpp;
}
/* copy the next block */
#pragma cdir loopcnt=LOOPCNT
#pragma cdir shortloop
for (i=0; i<ni; i++) {
/* for some reason int to float, for putn, requires a special case */
d = tp[i];
xp[i] = (int) Max( X_INT_MIN, Min(X_INT_MAX, (int) d));
nrange += d < X_INT_MIN || d > X_INT_MAX;
}
/* copy workspace back if necessary */
if (realign) {
memcpy(*xpp, tmp, ni*X_SIZEOF_INT);
xp = (int *) *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 += X_SIZEOF_INT, tp++)
{
int lstatus = ncx_put_int_float(xp, tp);
if(lstatus != ENOERR)
status = lstatus;
}
*xpp = (void *)xp;
return status;
#endif
}
int
ncx_putn_int_double(void **xpp, size_t nelems, const double *tp)
{
#if _SX && \
X_SIZEOF_INT == SIZEOF_INT
/* 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;
int tmp[LOOPCNT]; /* in case input is misaligned */
int *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) % SIZEOF_INT;
/* 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 = (int *) *xpp;
}
/* copy the next block */
#pragma cdir loopcnt=LOOPCNT
#pragma cdir shortloop
for (i=0; i<ni; i++) {
/* the normal case: */
xp[i] = (int) Max( X_INT_MIN, Min(X_INT_MAX, (int) tp[i]));
/* test for range errors (not always needed but do it anyway) */
nrange += tp[i] < X_INT_MIN || tp[i] > X_INT_MAX;
}
/* copy workspace back if necessary */
if (realign) {
memcpy(*xpp, tmp, ni*X_SIZEOF_INT);
xp = (int *) *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 += X_SIZEOF_INT, tp++)
{
int lstatus = ncx_put_int_double(xp, tp);
if(lstatus != ENOERR)
status = lstatus;
}
*xpp = (void *)xp;
return status;
#endif
}
/* float */
int
ncx_getn_float_schar(const void **xpp, size_t nelems, schar *tp)
{
#if _SX && \
X_SIZEOF_FLOAT == SIZEOF_FLOAT
/* 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;
float tmp[LOOPCNT]; /* in case input is misaligned */
float *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) % SIZEOF_FLOAT;
/* 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*SIZEOF_FLOAT);
xp = tmp;
} else {
xp = (float *) *xpp;
}
/* copy the next block */
#pragma cdir loopcnt=LOOPCNT
#pragma cdir shortloop
for (i=0; i<ni; i++) {
tp[i] = (schar) Max( SCHAR_MIN, Min(SCHAR_MAX, (schar) xp[i]));
/* test for range errors (not always needed but do it anyway) */
nrange += xp[i] < SCHAR_MIN || xp[i] > SCHAR_MAX;
}
/* update xpp and tp */
if (realign) xp = (float *) *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 += X_SIZEOF_FLOAT, tp++)
{
const int lstatus = ncx_get_float_schar(xp, tp);
if(lstatus != ENOERR)
status = lstatus;
}
*xpp = (const void *)xp;
return status;
# endif
}
int
ncx_getn_float_uchar(const void **xpp, size_t nelems, uchar *tp)
{
#if _SX && \
X_SIZEOF_FLOAT == SIZEOF_FLOAT
/* 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;
float tmp[LOOPCNT]; /* in case input is misaligned */
float *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) % SIZEOF_FLOAT;
/* 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*SIZEOF_FLOAT);
xp = tmp;
} else {
xp = (float *) *xpp;
}
/* copy the next block */
#pragma cdir loopcnt=LOOPCNT
#pragma cdir shortloop
for (i=0; i<ni; i++) {
tp[i] = (uchar) Max( UCHAR_MIN, Min(UCHAR_MAX, (uchar) xp[i]));
/* test for range errors (not always needed but do it anyway) */
nrange += xp[i] < UCHAR_MIN || xp[i] > UCHAR_MAX;
}
/* update xpp and tp */
if (realign) xp = (float *) *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 += X_SIZEOF_FLOAT, tp++)
{
const int lstatus = ncx_get_float_uchar(xp, tp);
if(lstatus != ENOERR)
status = lstatus;
}
*xpp = (const void *)xp;
return status;
# endif
}
int
ncx_getn_float_short(const void **xpp, size_t nelems, short *tp)
{
#if _SX && \
X_SIZEOF_FLOAT == SIZEOF_FLOAT
/* 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;
float tmp[LOOPCNT]; /* in case input is misaligned */
float *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) % SIZEOF_FLOAT;
/* 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*SIZEOF_FLOAT);
xp = tmp;
} else {
xp = (float *) *xpp;
}
/* copy the next block */
#pragma cdir loopcnt=LOOPCNT
#pragma cdir shortloop
for (i=0; i<ni; i++) {
tp[i] = (short) Max( SHORT_MIN, Min(SHORT_MAX, (short) xp[i]));
/* test for range errors (not always needed but do it anyway) */
nrange += xp[i] < SHORT_MIN || xp[i] > SHORT_MAX;
}
/* update xpp and tp */
if (realign) xp = (float *) *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 += X_SIZEOF_FLOAT, tp++)
{
const int lstatus = ncx_get_float_short(xp, tp);
if(lstatus != ENOERR)
status = lstatus;
}
*xpp = (const void *)xp;
return status;
# endif
}
int
ncx_getn_float_int(const void **xpp, size_t nelems, int *tp)
{
#if _SX && \
X_SIZEOF_FLOAT == SIZEOF_FLOAT
/* 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;
float tmp[LOOPCNT]; /* in case input is misaligned */
float *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) % SIZEOF_FLOAT;
/* 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*SIZEOF_FLOAT);
xp = tmp;
} else {
xp = (float *) *xpp;
}
/* copy the next block */
#pragma cdir loopcnt=LOOPCNT
#pragma cdir shortloop
for (i=0; i<ni; i++) {
tp[i] = (int) Max( INT_MIN, Min(INT_MAX, (int) xp[i]));
/* test for range errors (not always needed but do it anyway) */
nrange += xp[i] < INT_MIN || xp[i] > INT_MAX;
}
/* update xpp and tp */
if (realign) xp = (float *) *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 += X_SIZEOF_FLOAT, tp++)
{
const int lstatus = ncx_get_float_int(xp, tp);
if(lstatus != ENOERR)
status = lstatus;
}
*xpp = (const void *)xp;
return status;
# endif
}
#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)
{
struct vax_single *const vsp = (struct vax_single *) ip;
const struct ieee_single *const isp =
(const struct ieee_single *) (*xpp);
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;
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
int
ncx_getn_float_double(const void **xpp, size_t nelems, double *tp)
{
#if _SX && \
X_SIZEOF_FLOAT == SIZEOF_FLOAT
/* 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;
float tmp[LOOPCNT]; /* in case input is misaligned */
float *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) % SIZEOF_FLOAT;
/* 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*SIZEOF_FLOAT);
xp = tmp;
} else {
xp = (float *) *xpp;
}
/* copy the next block */
#pragma cdir loopcnt=LOOPCNT
#pragma cdir shortloop
for (i=0; i<ni; i++) {
tp[i] = (double) Max( DOUBLE_MIN, Min(DOUBLE_MAX, (double) xp[i]));
/* test for range errors (not always needed but do it anyway) */
nrange += xp[i] < DOUBLE_MIN || xp[i] > DOUBLE_MAX;
}
/* update xpp and tp */
if (realign) xp = (float *) *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 += X_SIZEOF_FLOAT, tp++)
{
const int lstatus = ncx_get_float_double(xp, tp);
if(lstatus != ENOERR)
status = lstatus;
}
*xpp = (const void *)xp;
return status;
# endif
}
int
ncx_getn_float_uint(const void **xpp, size_t nelems, uint *tp)
{
#if _SX && \
X_SIZEOF_FLOAT == SIZEOF_FLOAT
/* 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;
float tmp[LOOPCNT]; /* in case input is misaligned */
float *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) % SIZEOF_FLOAT;
/* 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*SIZEOF_FLOAT);
xp = tmp;
} else {
xp = (float *) *xpp;
}
/* copy the next block */
#pragma cdir loopcnt=LOOPCNT
#pragma cdir shortloop
for (i=0; i<ni; i++) {
tp[i] = (uint) Max( UINT_MIN, Min(UINT_MAX, (uint) xp[i]));
/* test for range errors (not always needed but do it anyway) */
nrange += xp[i] < UINT_MIN || xp[i] > UINT_MAX;
}
/* update xpp and tp */
if (realign) xp = (float *) *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 += X_SIZEOF_FLOAT, tp++)
{
const int lstatus = ncx_get_float_uint(xp, tp);
if(lstatus != ENOERR)
status = lstatus;
}
*xpp = (const void *)xp;
return status;
# endif
}
int
ncx_getn_float_longlong(const void **xpp, size_t nelems, longlong *tp)
{
#if _SX && \
X_SIZEOF_FLOAT == SIZEOF_FLOAT
/* 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;
float tmp[LOOPCNT]; /* in case input is misaligned */
float *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) % SIZEOF_FLOAT;
/* 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*SIZEOF_FLOAT);
xp = tmp;
} else {
xp = (float *) *xpp;
}
/* copy the next block */
#pragma cdir loopcnt=LOOPCNT
#pragma cdir shortloop
for (i=0; i<ni; i++) {
tp[i] = (longlong) Max( LONGLONG_MIN, Min(LONGLONG_MAX, (longlong) xp[i]));
/* test for range errors (not always needed but do it anyway) */
nrange += xp[i] < LONGLONG_MIN || xp[i] > LONGLONG_MAX;
}
/* update xpp and tp */
if (realign) xp = (float *) *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 += X_SIZEOF_FLOAT, tp++)
{
const int lstatus = ncx_get_float_longlong(xp, tp);
if(lstatus != ENOERR)
status = lstatus;
}
*xpp = (const void *)xp;
return status;
# endif
}
int
ncx_getn_float_ulonglong(const void **xpp, size_t nelems, ulonglong *tp)
{
#if _SX && \
X_SIZEOF_FLOAT == SIZEOF_FLOAT
/* 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;
float tmp[LOOPCNT]; /* in case input is misaligned */
float *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) % SIZEOF_FLOAT;
/* 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*SIZEOF_FLOAT);
xp = tmp;
} else {
xp = (float *) *xpp;
}
/* copy the next block */
#pragma cdir loopcnt=LOOPCNT
#pragma cdir shortloop
for (i=0; i<ni; i++) {
tp[i] = (ulonglong) Max( ULONGLONG_MIN, Min(ULONGLONG_MAX, (ulonglong) xp[i]));
/* test for range errors (not always needed but do it anyway) */
nrange += xp[i] < ULONGLONG_MIN || xp[i] > ULONGLONG_MAX;
}
/* update xpp and tp */
if (realign) xp = (float *) *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 += X_SIZEOF_FLOAT, tp++)
{
const int lstatus = ncx_get_float_ulonglong(xp, tp);
if(lstatus != ENOERR)
status = lstatus;
}
*xpp = (const void *)xp;
return status;
# endif
}
int
ncx_putn_float_schar(void **xpp, size_t nelems, const schar *tp)
{
#if _SX && \
X_SIZEOF_FLOAT == SIZEOF_FLOAT
/* 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;
float tmp[LOOPCNT]; /* in case input is misaligned */
float *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) % SIZEOF_FLOAT;
/* 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 = (float *) *xpp;
}
/* copy the next block */
#pragma cdir loopcnt=LOOPCNT
#pragma cdir shortloop
for (i=0; i<ni; i++) {
/* the normal case: */
xp[i] = (float) Max( X_FLOAT_MIN, Min(X_FLOAT_MAX, (float) tp[i]));
/* test for range errors (not always needed but do it anyway) */
nrange += tp[i] < X_FLOAT_MIN || tp[i] > X_FLOAT_MAX;
}
/* copy workspace back if necessary */
if (realign) {
memcpy(*xpp, tmp, ni*X_SIZEOF_FLOAT);
xp = (float *) *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 += X_SIZEOF_FLOAT, tp++)
{
int lstatus = ncx_put_float_schar(xp, tp);
if(lstatus != ENOERR)
status = lstatus;
}
*xpp = (void *)xp;
return status;
#endif
}
int
ncx_putn_float_uchar(void **xpp, size_t nelems, const uchar *tp)
{
#if _SX && \
X_SIZEOF_FLOAT == SIZEOF_FLOAT
/* 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;
float tmp[LOOPCNT]; /* in case input is misaligned */
float *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) % SIZEOF_FLOAT;
/* 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 = (float *) *xpp;
}
/* copy the next block */
#pragma cdir loopcnt=LOOPCNT
#pragma cdir shortloop
for (i=0; i<ni; i++) {
/* the normal case: */
xp[i] = (float) Max( X_FLOAT_MIN, Min(X_FLOAT_MAX, (float) tp[i]));
/* test for range errors (not always needed but do it anyway) */
nrange += tp[i] < X_FLOAT_MIN || tp[i] > X_FLOAT_MAX;
}
/* copy workspace back if necessary */
if (realign) {
memcpy(*xpp, tmp, ni*X_SIZEOF_FLOAT);
xp = (float *) *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 += X_SIZEOF_FLOAT, tp++)
{
int lstatus = ncx_put_float_uchar(xp, tp);
if(lstatus != ENOERR)
status = lstatus;
}
*xpp = (void *)xp;
return status;
#endif
}
int
ncx_putn_float_short(void **xpp, size_t nelems, const short *tp)
{
#if _SX && \
X_SIZEOF_FLOAT == SIZEOF_FLOAT
/* 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;
float tmp[LOOPCNT]; /* in case input is misaligned */
float *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) % SIZEOF_FLOAT;
/* 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 = (float *) *xpp;
}
/* copy the next block */
#pragma cdir loopcnt=LOOPCNT
#pragma cdir shortloop
for (i=0; i<ni; i++) {
/* the normal case: */
xp[i] = (float) Max( X_FLOAT_MIN, Min(X_FLOAT_MAX, (float) tp[i]));
/* test for range errors (not always needed but do it anyway) */
nrange += tp[i] < X_FLOAT_MIN || tp[i] > X_FLOAT_MAX;
}
/* copy workspace back if necessary */
if (realign) {
memcpy(*xpp, tmp, ni*X_SIZEOF_FLOAT);
xp = (float *) *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 += X_SIZEOF_FLOAT, tp++)
{
int lstatus = ncx_put_float_short(xp, tp);
if(lstatus != ENOERR)
status = lstatus;
}
*xpp = (void *)xp;
return status;
#endif
}
int
ncx_putn_float_int(void **xpp, size_t nelems, const int *tp)
{
#if _SX && \
X_SIZEOF_FLOAT == SIZEOF_FLOAT
/* 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;
float tmp[LOOPCNT]; /* in case input is misaligned */
float *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) % SIZEOF_FLOAT;
/* 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 = (float *) *xpp;
}
/* copy the next block */
#pragma cdir loopcnt=LOOPCNT
#pragma cdir shortloop
for (i=0; i<ni; i++) {
/* the normal case: */
xp[i] = (float) Max( X_FLOAT_MIN, Min(X_FLOAT_MAX, (float) tp[i]));
/* test for range errors (not always needed but do it anyway) */
nrange += tp[i] < X_FLOAT_MIN || tp[i] > X_FLOAT_MAX;
}
/* copy workspace back if necessary */
if (realign) {
memcpy(*xpp, tmp, ni*X_SIZEOF_FLOAT);
xp = (float *) *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 += X_SIZEOF_FLOAT, tp++)
{
int lstatus = ncx_put_float_int(xp, tp);
if(lstatus != ENOERR)
status = lstatus;
}
*xpp = (void *)xp;
return status;
#endif
}
#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)
{
const struct vax_single *const vsp =
(const struct vax_single *)ip;
struct ieee_single *const isp = (struct ieee_single *) (*xpp);
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;
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
int
ncx_putn_float_double(void **xpp, size_t nelems, const double *tp)
{
#if _SX && \
X_SIZEOF_FLOAT == SIZEOF_FLOAT
/* 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;
float tmp[LOOPCNT]; /* in case input is misaligned */
float *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) % SIZEOF_FLOAT;
/* 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 = (float *) *xpp;
}
/* copy the next block */
#pragma cdir loopcnt=LOOPCNT
#pragma cdir shortloop
for (i=0; i<ni; i++) {
/* the normal case: */
xp[i] = (float) Max( X_FLOAT_MIN, Min(X_FLOAT_MAX, (float) tp[i]));
/* test for range errors (not always needed but do it anyway) */
nrange += tp[i] < X_FLOAT_MIN || tp[i] > X_FLOAT_MAX;
}
/* copy workspace back if necessary */
if (realign) {
memcpy(*xpp, tmp, ni*X_SIZEOF_FLOAT);
xp = (float *) *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 += X_SIZEOF_FLOAT, tp++)
{
int lstatus = ncx_put_float_double(xp, tp);
if(lstatus != ENOERR)
status = lstatus;
}
*xpp = (void *)xp;
return status;
#endif
}
int
ncx_putn_float_uint(void **xpp, size_t nelems, const uint *tp)
{
#if _SX && \
X_SIZEOF_FLOAT == SIZEOF_FLOAT
/* 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;
float tmp[LOOPCNT]; /* in case input is misaligned */
float *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) % SIZEOF_FLOAT;
/* 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 = (float *) *xpp;
}
/* copy the next block */
#pragma cdir loopcnt=LOOPCNT
#pragma cdir shortloop
for (i=0; i<ni; i++) {
/* the normal case: */
xp[i] = (float) Max( X_FLOAT_MIN, Min(X_FLOAT_MAX, (float) tp[i]));
/* test for range errors (not always needed but do it anyway) */
nrange += tp[i] < X_FLOAT_MIN || tp[i] > X_FLOAT_MAX;
}
/* copy workspace back if necessary */
if (realign) {
memcpy(*xpp, tmp, ni*X_SIZEOF_FLOAT);
xp = (float *) *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 += X_SIZEOF_FLOAT, tp++)
{
int lstatus = ncx_put_float_uint(xp, tp);
if(lstatus != ENOERR)
status = lstatus;
}
*xpp = (void *)xp;
return status;
#endif
}
int
ncx_putn_float_longlong(void **xpp, size_t nelems, const longlong *tp)
{
#if _SX && \
X_SIZEOF_FLOAT == SIZEOF_FLOAT
/* 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;
float tmp[LOOPCNT]; /* in case input is misaligned */
float *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) % SIZEOF_FLOAT;
/* 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 = (float *) *xpp;
}
/* copy the next block */
#pragma cdir loopcnt=LOOPCNT
#pragma cdir shortloop
for (i=0; i<ni; i++) {
/* the normal case: */
xp[i] = (float) Max( X_FLOAT_MIN, Min(X_FLOAT_MAX, (float) tp[i]));
/* test for range errors (not always needed but do it anyway) */
nrange += tp[i] < X_FLOAT_MIN || tp[i] > X_FLOAT_MAX;
}
/* copy workspace back if necessary */
if (realign) {
memcpy(*xpp, tmp, ni*X_SIZEOF_FLOAT);
xp = (float *) *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 += X_SIZEOF_FLOAT, tp++)
{
int lstatus = ncx_put_float_longlong(xp, tp);
if(lstatus != ENOERR)
status = lstatus;
}
*xpp = (void *)xp;
return status;
#endif
}
int
ncx_putn_float_ulonglong(void **xpp, size_t nelems, const ulonglong *tp)
{
#if _SX && \
X_SIZEOF_FLOAT == SIZEOF_FLOAT
/* 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;
float tmp[LOOPCNT]; /* in case input is misaligned */
float *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) % SIZEOF_FLOAT;
/* 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 = (float *) *xpp;
}
/* copy the next block */
#pragma cdir loopcnt=LOOPCNT
#pragma cdir shortloop
for (i=0; i<ni; i++) {
/* the normal case: */
xp[i] = (float) Max( X_FLOAT_MIN, Min(X_FLOAT_MAX, (float) tp[i]));
/* test for range errors (not always needed but do it anyway) */
nrange += tp[i] < X_FLOAT_MIN || tp[i] > X_FLOAT_MAX;
}
/* copy workspace back if necessary */
if (realign) {
memcpy(*xpp, tmp, ni*X_SIZEOF_FLOAT);
xp = (float *) *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 += X_SIZEOF_FLOAT, tp++)
{
int lstatus = ncx_put_float_ulonglong(xp, tp);
if(lstatus != ENOERR)
status = lstatus;
}
*xpp = (void *)xp;
return status;
#endif
}
/* double */
int
ncx_getn_double_schar(const void **xpp, size_t nelems, schar *tp)
{
#if _SX && \
X_SIZEOF_DOUBLE == SIZEOF_DOUBLE
/* 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;
double tmp[LOOPCNT]; /* in case input is misaligned */
double *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) % SIZEOF_DOUBLE;
/* 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*SIZEOF_DOUBLE);
xp = tmp;
} else {
xp = (double *) *xpp;
}
/* copy the next block */
#pragma cdir loopcnt=LOOPCNT
#pragma cdir shortloop
for (i=0; i<ni; i++) {
tp[i] = (schar) Max( SCHAR_MIN, Min(SCHAR_MAX, (schar) xp[i]));
/* test for range errors (not always needed but do it anyway) */
nrange += xp[i] < SCHAR_MIN || xp[i] > SCHAR_MAX;
}
/* update xpp and tp */
if (realign) xp = (double *) *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 += X_SIZEOF_DOUBLE, tp++)
{
const int lstatus = ncx_get_double_schar(xp, tp);
if(lstatus != ENOERR)
status = lstatus;
}
*xpp = (const void *)xp;
return status;
# endif
}
int
ncx_getn_double_uchar(const void **xpp, size_t nelems, uchar *tp)
{
#if _SX && \
X_SIZEOF_DOUBLE == SIZEOF_DOUBLE
/* 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;
double tmp[LOOPCNT]; /* in case input is misaligned */
double *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) % SIZEOF_DOUBLE;
/* 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*SIZEOF_DOUBLE);
xp = tmp;
} else {
xp = (double *) *xpp;
}
/* copy the next block */
#pragma cdir loopcnt=LOOPCNT
#pragma cdir shortloop
for (i=0; i<ni; i++) {
tp[i] = (uchar) Max( UCHAR_MIN, Min(UCHAR_MAX, (uchar) xp[i]));
/* test for range errors (not always needed but do it anyway) */
nrange += xp[i] < UCHAR_MIN || xp[i] > UCHAR_MAX;
}
/* update xpp and tp */
if (realign) xp = (double *) *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 += X_SIZEOF_DOUBLE, tp++)
{
const int lstatus = ncx_get_double_uchar(xp, tp);
if(lstatus != ENOERR)
status = lstatus;
}
*xpp = (const void *)xp;
return status;
# endif
}
int
ncx_getn_double_short(const void **xpp, size_t nelems, short *tp)
{
#if _SX && \
X_SIZEOF_DOUBLE == SIZEOF_DOUBLE
/* 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;
double tmp[LOOPCNT]; /* in case input is misaligned */
double *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) % SIZEOF_DOUBLE;
/* 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*SIZEOF_DOUBLE);
xp = tmp;
} else {
xp = (double *) *xpp;
}
/* copy the next block */
#pragma cdir loopcnt=LOOPCNT
#pragma cdir shortloop
for (i=0; i<ni; i++) {
tp[i] = (short) Max( SHORT_MIN, Min(SHORT_MAX, (short) xp[i]));
/* test for range errors (not always needed but do it anyway) */
nrange += xp[i] < SHORT_MIN || xp[i] > SHORT_MAX;
}
/* update xpp and tp */
if (realign) xp = (double *) *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 += X_SIZEOF_DOUBLE, tp++)
{
const int lstatus = ncx_get_double_short(xp, tp);
if(lstatus != ENOERR)
status = lstatus;
}
*xpp = (const void *)xp;
return status;
# endif
}
int
ncx_getn_double_int(const void **xpp, size_t nelems, int *tp)
{
#if _SX && \
X_SIZEOF_DOUBLE == SIZEOF_DOUBLE
/* 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;
double tmp[LOOPCNT]; /* in case input is misaligned */
double *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) % SIZEOF_DOUBLE;
/* 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*SIZEOF_DOUBLE);
xp = tmp;
} else {
xp = (double *) *xpp;
}
/* copy the next block */
#pragma cdir loopcnt=LOOPCNT
#pragma cdir shortloop
for (i=0; i<ni; i++) {
tp[i] = (int) Max( INT_MIN, Min(INT_MAX, (int) xp[i]));
/* test for range errors (not always needed but do it anyway) */
nrange += xp[i] < INT_MIN || xp[i] > INT_MAX;
}
/* update xpp and tp */
if (realign) xp = (double *) *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 += X_SIZEOF_DOUBLE, tp++)
{
const int lstatus = ncx_get_double_int(xp, tp);
if(lstatus != ENOERR)
status = lstatus;
}
*xpp = (const void *)xp;
return status;
# endif
}
int
ncx_getn_double_float(const void **xpp, size_t nelems, float *tp)
{
#if _SX && \
X_SIZEOF_DOUBLE == SIZEOF_DOUBLE
/* 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;
double tmp[LOOPCNT]; /* in case input is misaligned */
double *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) % SIZEOF_DOUBLE;
/* 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*SIZEOF_DOUBLE);
xp = tmp;
} else {
xp = (double *) *xpp;
}
/* copy the next block */
#pragma cdir loopcnt=LOOPCNT
#pragma cdir shortloop
for (i=0; i<ni; i++) {
tp[i] = (float) Max( FLOAT_MIN, Min(FLOAT_MAX, (float) xp[i]));
/* test for range errors (not always needed but do it anyway) */
nrange += xp[i] < FLOAT_MIN || xp[i] > FLOAT_MAX;
}
/* update xpp and tp */
if (realign) xp = (double *) *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 += X_SIZEOF_DOUBLE, tp++)
{
const int lstatus = ncx_get_double_float(xp, tp);
if(lstatus != ENOERR)
status = lstatus;
}
*xpp = (const void *)xp;
return status;
# endif
}
int
ncx_getn_double_uint(const void **xpp, size_t nelems, uint *tp)
{
#if _SX && \
X_SIZEOF_DOUBLE == SIZEOF_DOUBLE
/* 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;
double tmp[LOOPCNT]; /* in case input is misaligned */
double *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) % SIZEOF_DOUBLE;
/* 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*SIZEOF_DOUBLE);
xp = tmp;
} else {
xp = (double *) *xpp;
}
/* copy the next block */
#pragma cdir loopcnt=LOOPCNT
#pragma cdir shortloop
for (i=0; i<ni; i++) {
tp[i] = (uint) Max( UINT_MIN, Min(UINT_MAX, (uint) xp[i]));
/* test for range errors (not always needed but do it anyway) */
nrange += xp[i] < UINT_MIN || xp[i] > UINT_MAX;
}
/* update xpp and tp */
if (realign) xp = (double *) *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 += X_SIZEOF_DOUBLE, tp++)
{
const int lstatus = ncx_get_double_uint(xp, tp);
if(lstatus != ENOERR)
status = lstatus;
}
*xpp = (const void *)xp;
return status;
# endif
}
int
ncx_getn_double_longlong(const void **xpp, size_t nelems, longlong *tp)
{
#if _SX && \
X_SIZEOF_DOUBLE == SIZEOF_DOUBLE
/* 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;
double tmp[LOOPCNT]; /* in case input is misaligned */
double *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) % SIZEOF_DOUBLE;
/* 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*SIZEOF_DOUBLE);
xp = tmp;
} else {
xp = (double *) *xpp;
}
/* copy the next block */
#pragma cdir loopcnt=LOOPCNT
#pragma cdir shortloop
for (i=0; i<ni; i++) {
tp[i] = (longlong) Max( LONGLONG_MIN, Min(LONGLONG_MAX, (longlong) xp[i]));
/* test for range errors (not always needed but do it anyway) */
nrange += xp[i] < LONGLONG_MIN || xp[i] > LONGLONG_MAX;
}
/* update xpp and tp */
if (realign) xp = (double *) *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 += X_SIZEOF_DOUBLE, tp++)
{
const int lstatus = ncx_get_double_longlong(xp, tp);
if(lstatus != ENOERR)
status = lstatus;
}
*xpp = (const void *)xp;
return status;
# endif
}
int
ncx_getn_double_ulonglong(const void **xpp, size_t nelems, ulonglong *tp)
{
#if _SX && \
X_SIZEOF_DOUBLE == SIZEOF_DOUBLE
/* 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;
double tmp[LOOPCNT]; /* in case input is misaligned */
double *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) % SIZEOF_DOUBLE;
/* 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*SIZEOF_DOUBLE);
xp = tmp;
} else {
xp = (double *) *xpp;
}
/* copy the next block */
#pragma cdir loopcnt=LOOPCNT
#pragma cdir shortloop
for (i=0; i<ni; i++) {
tp[i] = (ulonglong) Max( ULONGLONG_MIN, Min(ULONGLONG_MAX, (ulonglong) xp[i]));
/* test for range errors (not always needed but do it anyway) */
nrange += xp[i] < ULONGLONG_MIN || xp[i] > ULONGLONG_MAX;
}
/* update xpp and tp */
if (realign) xp = (double *) *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 += X_SIZEOF_DOUBLE, tp++)
{
const int lstatus = ncx_get_double_ulonglong(xp, tp);
if(lstatus != ENOERR)
status = lstatus;
}
*xpp = (const void *)xp;
return status;
# endif
}
#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)
{
struct vax_double *const vdp =
(struct vax_double *)ip;
const struct ieee_double *const idp =
(const struct ieee_double *) (*xpp);
{
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;
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
int
ncx_putn_double_schar(void **xpp, size_t nelems, const schar *tp)
{
#if _SX && \
X_SIZEOF_DOUBLE == SIZEOF_DOUBLE
/* 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;
double tmp[LOOPCNT]; /* in case input is misaligned */
double *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) % SIZEOF_DOUBLE;
/* 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 = (double *) *xpp;
}
/* copy the next block */
#pragma cdir loopcnt=LOOPCNT
#pragma cdir shortloop
for (i=0; i<ni; i++) {
/* the normal case: */
xp[i] = (double) Max( X_DOUBLE_MIN, Min(X_DOUBLE_MAX, (double) tp[i]));
/* test for range errors (not always needed but do it anyway) */
nrange += tp[i] < X_DOUBLE_MIN || tp[i] > X_DOUBLE_MAX;
}
/* copy workspace back if necessary */
if (realign) {
memcpy(*xpp, tmp, ni*X_SIZEOF_DOUBLE);
xp = (double *) *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 += X_SIZEOF_DOUBLE, tp++)
{
int lstatus = ncx_put_double_schar(xp, tp);
if(lstatus != ENOERR)
status = lstatus;
}
*xpp = (void *)xp;
return status;
#endif
}
int
ncx_putn_double_uchar(void **xpp, size_t nelems, const uchar *tp)
{
#if _SX && \
X_SIZEOF_DOUBLE == SIZEOF_DOUBLE
/* 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;
double tmp[LOOPCNT]; /* in case input is misaligned */
double *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) % SIZEOF_DOUBLE;
/* 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 = (double *) *xpp;
}
/* copy the next block */
#pragma cdir loopcnt=LOOPCNT
#pragma cdir shortloop
for (i=0; i<ni; i++) {
/* the normal case: */
xp[i] = (double) Max( X_DOUBLE_MIN, Min(X_DOUBLE_MAX, (double) tp[i]));
/* test for range errors (not always needed but do it anyway) */
nrange += tp[i] < X_DOUBLE_MIN || tp[i] > X_DOUBLE_MAX;
}
/* copy workspace back if necessary */
if (realign) {
memcpy(*xpp, tmp, ni*X_SIZEOF_DOUBLE);
xp = (double *) *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 += X_SIZEOF_DOUBLE, tp++)
{
int lstatus = ncx_put_double_uchar(xp, tp);
if(lstatus != ENOERR)
status = lstatus;
}
*xpp = (void *)xp;
return status;
#endif
}
int
ncx_putn_double_short(void **xpp, size_t nelems, const short *tp)
{
#if _SX && \
X_SIZEOF_DOUBLE == SIZEOF_DOUBLE
/* 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;
double tmp[LOOPCNT]; /* in case input is misaligned */
double *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) % SIZEOF_DOUBLE;
/* 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 = (double *) *xpp;
}
/* copy the next block */
#pragma cdir loopcnt=LOOPCNT
#pragma cdir shortloop
for (i=0; i<ni; i++) {
/* the normal case: */
xp[i] = (double) Max( X_DOUBLE_MIN, Min(X_DOUBLE_MAX, (double) tp[i]));
/* test for range errors (not always needed but do it anyway) */
nrange += tp[i] < X_DOUBLE_MIN || tp[i] > X_DOUBLE_MAX;
}
/* copy workspace back if necessary */
if (realign) {
memcpy(*xpp, tmp, ni*X_SIZEOF_DOUBLE);
xp = (double *) *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 += X_SIZEOF_DOUBLE, tp++)
{
int lstatus = ncx_put_double_short(xp, tp);
if(lstatus != ENOERR)
status = lstatus;
}
*xpp = (void *)xp;
return status;
#endif
}
int
ncx_putn_double_int(void **xpp, size_t nelems, const int *tp)
{
#if _SX && \
X_SIZEOF_DOUBLE == SIZEOF_DOUBLE
/* 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;
double tmp[LOOPCNT]; /* in case input is misaligned */
double *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) % SIZEOF_DOUBLE;
/* 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 = (double *) *xpp;
}
/* copy the next block */
#pragma cdir loopcnt=LOOPCNT
#pragma cdir shortloop
for (i=0; i<ni; i++) {
/* the normal case: */
xp[i] = (double) Max( X_DOUBLE_MIN, Min(X_DOUBLE_MAX, (double) tp[i]));
/* test for range errors (not always needed but do it anyway) */
nrange += tp[i] < X_DOUBLE_MIN || tp[i] > X_DOUBLE_MAX;
}
/* copy workspace back if necessary */
if (realign) {
memcpy(*xpp, tmp, ni*X_SIZEOF_DOUBLE);
xp = (double *) *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 += X_SIZEOF_DOUBLE, tp++)
{
int lstatus = ncx_put_double_int(xp, tp);
if(lstatus != ENOERR)
status = lstatus;
}
*xpp = (void *)xp;
return status;
#endif
}
int
ncx_putn_double_float(void **xpp, size_t nelems, const float *tp)
{
#if _SX && \
X_SIZEOF_DOUBLE == SIZEOF_DOUBLE
/* 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;
double tmp[LOOPCNT]; /* in case input is misaligned */
double *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) % SIZEOF_DOUBLE;
/* 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 = (double *) *xpp;
}
/* copy the next block */
#pragma cdir loopcnt=LOOPCNT
#pragma cdir shortloop
for (i=0; i<ni; i++) {
/* the normal case: */
xp[i] = (double) Max( X_DOUBLE_MIN, Min(X_DOUBLE_MAX, (double) tp[i]));
/* test for range errors (not always needed but do it anyway) */
nrange += tp[i] < X_DOUBLE_MIN || tp[i] > X_DOUBLE_MAX;
}
/* copy workspace back if necessary */
if (realign) {
memcpy(*xpp, tmp, ni*X_SIZEOF_DOUBLE);
xp = (double *) *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 += X_SIZEOF_DOUBLE, tp++)
{
int lstatus = ncx_put_double_float(xp, tp);
if(lstatus != ENOERR)
status = lstatus;
}
*xpp = (void *)xp;
return status;
#endif
}
int
ncx_putn_double_uint(void **xpp, size_t nelems, const uint *tp)
{
#if _SX && \
X_SIZEOF_DOUBLE == SIZEOF_DOUBLE
/* 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;
double tmp[LOOPCNT]; /* in case input is misaligned */
double *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) % SIZEOF_DOUBLE;
/* 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 = (double *) *xpp;
}
/* copy the next block */
#pragma cdir loopcnt=LOOPCNT
#pragma cdir shortloop
for (i=0; i<ni; i++) {
/* the normal case: */
xp[i] = (double) Max( X_DOUBLE_MIN, Min(X_DOUBLE_MAX, (double) tp[i]));
/* test for range errors (not always needed but do it anyway) */
nrange += tp[i] < X_DOUBLE_MIN || tp[i] > X_DOUBLE_MAX;
}
/* copy workspace back if necessary */
if (realign) {
memcpy(*xpp, tmp, ni*X_SIZEOF_DOUBLE);
xp = (double *) *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 += X_SIZEOF_DOUBLE, tp++)
{
int lstatus = ncx_put_double_uint(xp, tp);
if(lstatus != ENOERR)
status = lstatus;
}
*xpp = (void *)xp;
return status;
#endif
}
int
ncx_putn_double_longlong(void **xpp, size_t nelems, const longlong *tp)
{
#if _SX && \
X_SIZEOF_DOUBLE == SIZEOF_DOUBLE
/* 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;
double tmp[LOOPCNT]; /* in case input is misaligned */
double *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) % SIZEOF_DOUBLE;
/* 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 = (double *) *xpp;
}
/* copy the next block */
#pragma cdir loopcnt=LOOPCNT
#pragma cdir shortloop
for (i=0; i<ni; i++) {
/* the normal case: */
xp[i] = (double) Max( X_DOUBLE_MIN, Min(X_DOUBLE_MAX, (double) tp[i]));
/* test for range errors (not always needed but do it anyway) */
nrange += tp[i] < X_DOUBLE_MIN || tp[i] > X_DOUBLE_MAX;
}
/* copy workspace back if necessary */
if (realign) {
memcpy(*xpp, tmp, ni*X_SIZEOF_DOUBLE);
xp = (double *) *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 += X_SIZEOF_DOUBLE, tp++)
{
int lstatus = ncx_put_double_longlong(xp, tp);
if(lstatus != ENOERR)
status = lstatus;
}
*xpp = (void *)xp;
return status;
#endif
}
int
ncx_putn_double_ulonglong(void **xpp, size_t nelems, const ulonglong *tp)
{
#if _SX && \
X_SIZEOF_DOUBLE == SIZEOF_DOUBLE
/* 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;
double tmp[LOOPCNT]; /* in case input is misaligned */
double *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) % SIZEOF_DOUBLE;
/* 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 = (double *) *xpp;
}
/* copy the next block */
#pragma cdir loopcnt=LOOPCNT
#pragma cdir shortloop
for (i=0; i<ni; i++) {
/* the normal case: */
xp[i] = (double) Max( X_DOUBLE_MIN, Min(X_DOUBLE_MAX, (double) tp[i]));
/* test for range errors (not always needed but do it anyway) */
nrange += tp[i] < X_DOUBLE_MIN || tp[i] > X_DOUBLE_MAX;
}
/* copy workspace back if necessary */
if (realign) {
memcpy(*xpp, tmp, ni*X_SIZEOF_DOUBLE);
xp = (double *) *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 += X_SIZEOF_DOUBLE, tp++)
{
int lstatus = ncx_put_double_ulonglong(xp, tp);
if(lstatus != ENOERR)
status = lstatus;
}
*xpp = (void *)xp;
return status;
#endif
}
#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)
{
const struct vax_double *const vdp =
(const struct vax_double *)ip;
struct ieee_double *const idp =
(struct ieee_double *) (*xpp);
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;
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
/*
* Other aggregate conversion functions.
*/
/* text */
int
ncx_getn_text(const void **xpp, size_t nelems, char *tp)
{
(void) memcpy(tp, *xpp, nelems);
*xpp = (void *)((char *)(*xpp) + nelems);
return ENOERR;
}
int
ncx_pad_getn_text(const void **xpp, size_t nelems, char *tp)
{
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;
}
int
ncx_putn_text(void **xpp, size_t nelems, const char *tp)
{
(void) memcpy(*xpp, tp, nelems);
*xpp = (void *)((char *)(*xpp) + nelems);
return ENOERR;
}
int
ncx_pad_putn_text(void **xpp, size_t nelems, const char *tp)
{
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;
}
/* opaque */
int
ncx_getn_void(const void **xpp, size_t nelems, void *tp)
{
(void) memcpy(tp, *xpp, nelems);
*xpp = (void *)((char *)(*xpp) + nelems);
return ENOERR;
}
int
ncx_pad_getn_void(const void **xpp, size_t nelems, void *tp)
{
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;
}
int
ncx_putn_void(void **xpp, size_t nelems, const void *tp)
{
(void) memcpy(*xpp, tp, nelems);
*xpp = (void *)((char *)(*xpp) + nelems);
return ENOERR;
}
int
ncx_pad_putn_void(void **xpp, size_t nelems, const void *tp)
{
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;
}