/* Do not edit this file. It is produced from the corresponding .m4 source */
/*
 *  Copyright (C) 2003, Northwestern University and Argonne National Laboratory
 *  See COPYRIGHT notice in top-level directory.
 */
/* $Id: test_put.m4 2672 2016-12-03 19:23:53Z wkliao $ */


#include "tests.h"

#ifdef USE_PNETCDF
#include <pnetcdf.h>
#ifndef PNETCDF_VERSION_MAJOR
#error("PNETCDF_VERSION_MAJOR is not defined in pnetcdf.h")
#endif
#ifndef PNETCDF_VERSION_MINOR
#error("PNETCDF_VERSION_MAJOR is not defined in pnetcdf.h")
#endif
#endif










/*
 *  ensure hash value within range for internal TYPE
 */
text
hash_text(const int       cdf_format,
        const nc_type   type,
        const int       rank,
        const size_t  *index,
        const nct_itype itype)
{
    double value;

    value = hash4(cdf_format, type, rank, index, itype);
    return (text)value;
}

/*
 *  ensure hash value within range for internal TYPE
 */
uchar
hash_uchar(const int       cdf_format,
        const nc_type   type,
        const int       rank,
        const size_t  *index,
        const nct_itype itype)
{
    double value;

    value = hash4(cdf_format, type, rank, index, itype);
    
    if (value > uchar_max) return uchar_max;
    else if (value < uchar_min) return uchar_min;
    else return (uchar)value;
}

/*
 *  ensure hash value within range for internal TYPE
 */
schar
hash_schar(const int       cdf_format,
        const nc_type   type,
        const int       rank,
        const size_t  *index,
        const nct_itype itype)
{
    double value;

    value = hash4(cdf_format, type, rank, index, itype);
    
    if (value > schar_max) return schar_max;
    else if (value < schar_min) return schar_min;
    else return (schar)value;
}

/*
 *  ensure hash value within range for internal TYPE
 */
short
hash_short(const int       cdf_format,
        const nc_type   type,
        const int       rank,
        const size_t  *index,
        const nct_itype itype)
{
    double value;

    value = hash4(cdf_format, type, rank, index, itype);
    
    if (value > short_max) return short_max;
    else if (value < short_min) return short_min;
    else return (short)value;
}

/*
 *  ensure hash value within range for internal TYPE
 */
int
hash_int(const int       cdf_format,
        const nc_type   type,
        const int       rank,
        const size_t  *index,
        const nct_itype itype)
{
    double value;

    value = hash4(cdf_format, type, rank, index, itype);
    
    if (value > int_max) return int_max;
    else if (value < int_min) return int_min;
    else return (int)value;
}

/*
 *  ensure hash value within range for internal TYPE
 */
long
hash_long(const int       cdf_format,
        const nc_type   type,
        const int       rank,
        const size_t  *index,
        const nct_itype itype)
{
    double value;

    value = hash4(cdf_format, type, rank, index, itype);
    
    if (value > long_max) return long_max;
    else if (value < long_min) return long_min;
    else return (long)value;
}

/*
 *  ensure hash value within range for internal TYPE
 */
float
hash_float(const int       cdf_format,
        const nc_type   type,
        const int       rank,
        const size_t  *index,
        const nct_itype itype)
{
    double value;

    value = hash4(cdf_format, type, rank, index, itype);
    
    if (value > float_max) return float_max;
    else if (value < float_min) return float_min;
    else return (float)value;
}

/*
 *  ensure hash value within range for internal TYPE
 */
double
hash_double(const int       cdf_format,
        const nc_type   type,
        const int       rank,
        const size_t  *index,
        const nct_itype itype)
{
    double value;

    value = hash4(cdf_format, type, rank, index, itype);
    
    if (value > double_max) return double_max;
    else if (value < double_min) return double_min;
    else return (double)value;
}

/*
 *  ensure hash value within range for internal TYPE
 */
ushort
hash_ushort(const int       cdf_format,
        const nc_type   type,
        const int       rank,
        const size_t  *index,
        const nct_itype itype)
{
    double value;

    value = hash4(cdf_format, type, rank, index, itype);
    
    if (value > ushort_max) return ushort_max;
    else if (value < ushort_min) return ushort_min;
    else return (ushort)value;
}

/*
 *  ensure hash value within range for internal TYPE
 */
uint
hash_uint(const int       cdf_format,
        const nc_type   type,
        const int       rank,
        const size_t  *index,
        const nct_itype itype)
{
    double value;

    value = hash4(cdf_format, type, rank, index, itype);
    
    if (value > uint_max) return uint_max;
    else if (value < uint_min) return uint_min;
    else return (uint)value;
}

/*
 *  ensure hash value within range for internal TYPE
 */
longlong
hash_longlong(const int       cdf_format,
        const nc_type   type,
        const int       rank,
        const size_t  *index,
        const nct_itype itype)
{
    double value;

    value = hash4(cdf_format, type, rank, index, itype);
    
    if (value > longlong_max) return longlong_max;
    else if (value < longlong_min) return longlong_min;
    else return (longlong)value;
}

/*
 *  ensure hash value within range for internal TYPE
 */
ulonglong
hash_ulonglong(const int       cdf_format,
        const nc_type   type,
        const int       rank,
        const size_t  *index,
        const nct_itype itype)
{
    double value;

    value = hash4(cdf_format, type, rank, index, itype);
    
    if (value > ulonglong_max) return ulonglong_max;
    else if (value < ulonglong_min) return ulonglong_min;
    else return (ulonglong)value;
}




/*
 *  check all vars in file which are (text/numeric) compatible with TYPE
 */
int
check_vars_text(const char *filename, int numVars)
{
    int i, d, err, ncid, cdf_format, ndims;
    int canConvert;   /* Both text or both numeric */
    int nok = 0;      /* count of valid comparisons */
    int dimids[MAX_RANK];
    nc_type datatype;
    char name[NC_MAX_NAME];
    size_t j, length, index[MAX_RANK];
    double expect;
    text value;

    err = file_open(filename, NC_NOWRITE, &ncid);
    IF (err != NC_NOERR) error("open: %s",  nc_strerror(err));

    err =  nc_inq_format(ncid, &cdf_format);
    IF (err != NC_NOERR) error("inq_format: %s",  nc_strerror(err));

    for (i = 0; i < numVars; i++) {
        canConvert = (var_type[i] == NC_CHAR) ;
        if (!canConvert) continue;

        err =  nc_inq_var(ncid, i, name, &datatype, &ndims, dimids, NULL);
        IF (err != NC_NOERR)
            error("inq_var: %s",  nc_strerror(err));
        IF (strcmp(name, var_name[i]) != 0)
            error("Unexpected var_name");
        IF (datatype != var_type[i])
            error("Unexpected type");
        IF (ndims != var_rank[i])
            error("Unexpected rank");
        for (j = 0; j < ndims; j++) {
            err =  nc_inq_dim(ncid, dimids[j], 0, &length);
            IF (err != NC_NOERR)
                error("inq_dim: %s",  nc_strerror(err));
            IF (length != var_shape[i][j])
                error("Unexpected shape");
        }
        for (j = 0; j < var_nels[i]; j++) {
            err = toMixedBase(j, var_rank[i], var_shape[i], index);
            IF (err != 0) error("error in toMixedBase");
            expect = hash4(cdf_format, var_type[i], var_rank[i], index,
                           NCT_TEXT);
            err = nc_get_var1_text(ncid, i, index, &value);
            if (1) {
                IF (err != NC_NOERR) {
                    error("nc_get_var1_text: %s",  nc_strerror(err));
                } else {
                    
                    IF (!equal((double)value,expect,var_type[i],NCT_TEXT)){
                        error("Var value read not that expected");
                        if (verbose) {
                            error("\n");
                            error("varid: %d, ", i);
                            error("var_name: %s, ", var_name[i]);
                            error("var_type: %s, ", s_nc_type(var_type[i]));
                            error("index:");
                            for (d = 0; d < var_rank[i]; d++)
                                error(" %d", index[d]);
                            error(", expect: %g, ", expect);
                            error("got: %g", (double) value);
                        }
                    } else {
                        ++nok;
                    }
                }
            }
        }
    }
    err =  nc_close(ncid);
    IF (err != NC_NOERR)
        error("close: %s",  nc_strerror(err));
    return nok;
}

/*
 *  check all vars in file which are (text/numeric) compatible with TYPE
 */
int
check_vars_uchar(const char *filename, int numVars)
{
    int i, d, err, ncid, cdf_format, ndims;
    int canConvert;   /* Both text or both numeric */
    int nok = 0;      /* count of valid comparisons */
    int dimids[MAX_RANK];
    nc_type datatype;
    char name[NC_MAX_NAME];
    size_t j, length, index[MAX_RANK];
    double expect;
    uchar value;

    err = file_open(filename, NC_NOWRITE, &ncid);
    IF (err != NC_NOERR) error("open: %s",  nc_strerror(err));

    err =  nc_inq_format(ncid, &cdf_format);
    IF (err != NC_NOERR) error("inq_format: %s",  nc_strerror(err));

    for (i = 0; i < numVars; i++) {
        canConvert = (var_type[i] == NC_CHAR) == (NCT_UCHAR == NCT_TEXT);
        if (!canConvert) continue;

        err =  nc_inq_var(ncid, i, name, &datatype, &ndims, dimids, NULL);
        IF (err != NC_NOERR)
            error("inq_var: %s",  nc_strerror(err));
        IF (strcmp(name, var_name[i]) != 0)
            error("Unexpected var_name");
        IF (datatype != var_type[i])
            error("Unexpected type");
        IF (ndims != var_rank[i])
            error("Unexpected rank");
        for (j = 0; j < ndims; j++) {
            err =  nc_inq_dim(ncid, dimids[j], 0, &length);
            IF (err != NC_NOERR)
                error("inq_dim: %s",  nc_strerror(err));
            IF (length != var_shape[i][j])
                error("Unexpected shape");
        }
        for (j = 0; j < var_nels[i]; j++) {
            err = toMixedBase(j, var_rank[i], var_shape[i], index);
            IF (err != 0) error("error in toMixedBase");
            expect = hash4(cdf_format, var_type[i], var_rank[i], index,
                           NCT_UCHAR);
            err = nc_get_var1_uchar(ncid, i, index, &value);
            if (inRange3(cdf_format, (double)expect,datatype,NCT_UCHAR) && (expect >= uchar_min && expect <= uchar_max)) {
                IF (err != NC_NOERR) {
                    error("nc_get_var1_uchar: %s",  nc_strerror(err));
                } else {
                    
                    /* In put_vars(), nc_put_vara_double() is used to write
                     * variables of type NC_BYTE to files. For uchar APIs,
                     * NC_BYTE variables are treated as unsigned for CDF-1 and 2
                     * formats. Thus, we skip the equal test for out-of-bound
                     * values below for uchar APIs.
                     */
                    if (cdf_format < NC_FORMAT_CDF5 &&
                        var_type[i] == NC_BYTE && expect > schar_max)
                        continue;
                    IF (!equal((double)value,expect,var_type[i],NCT_UCHAR)){
                        error("Var value read not that expected");
                        if (verbose) {
                            error("\n");
                            error("varid: %d, ", i);
                            error("var_name: %s, ", var_name[i]);
                            error("var_type: %s, ", s_nc_type(var_type[i]));
                            error("index:");
                            for (d = 0; d < var_rank[i]; d++)
                                error(" %d", index[d]);
                            error(", expect: %g, ", expect);
                            error("got: %g", (double) value);
                        }
                    } else {
                        ++nok;
                    }
                }
            }
        }
    }
    err =  nc_close(ncid);
    IF (err != NC_NOERR)
        error("close: %s",  nc_strerror(err));
    return nok;
}

/*
 *  check all vars in file which are (text/numeric) compatible with TYPE
 */
int
check_vars_schar(const char *filename, int numVars)
{
    int i, d, err, ncid, cdf_format, ndims;
    int canConvert;   /* Both text or both numeric */
    int nok = 0;      /* count of valid comparisons */
    int dimids[MAX_RANK];
    nc_type datatype;
    char name[NC_MAX_NAME];
    size_t j, length, index[MAX_RANK];
    double expect;
    schar value;

    err = file_open(filename, NC_NOWRITE, &ncid);
    IF (err != NC_NOERR) error("open: %s",  nc_strerror(err));

    err =  nc_inq_format(ncid, &cdf_format);
    IF (err != NC_NOERR) error("inq_format: %s",  nc_strerror(err));

    for (i = 0; i < numVars; i++) {
        canConvert = (var_type[i] == NC_CHAR) == (NCT_SCHAR == NCT_TEXT);
        if (!canConvert) continue;

        err =  nc_inq_var(ncid, i, name, &datatype, &ndims, dimids, NULL);
        IF (err != NC_NOERR)
            error("inq_var: %s",  nc_strerror(err));
        IF (strcmp(name, var_name[i]) != 0)
            error("Unexpected var_name");
        IF (datatype != var_type[i])
            error("Unexpected type");
        IF (ndims != var_rank[i])
            error("Unexpected rank");
        for (j = 0; j < ndims; j++) {
            err =  nc_inq_dim(ncid, dimids[j], 0, &length);
            IF (err != NC_NOERR)
                error("inq_dim: %s",  nc_strerror(err));
            IF (length != var_shape[i][j])
                error("Unexpected shape");
        }
        for (j = 0; j < var_nels[i]; j++) {
            err = toMixedBase(j, var_rank[i], var_shape[i], index);
            IF (err != 0) error("error in toMixedBase");
            expect = hash4(cdf_format, var_type[i], var_rank[i], index,
                           NCT_SCHAR);
            err = nc_get_var1_schar(ncid, i, index, &value);
            if (inRange3(cdf_format, (double)expect,datatype,NCT_SCHAR) && (expect >= schar_min && expect <= schar_max)) {
                IF (err != NC_NOERR) {
                    error("nc_get_var1_schar: %s",  nc_strerror(err));
                } else {
                    
                    IF (!equal((double)value,expect,var_type[i],NCT_SCHAR)){
                        error("Var value read not that expected");
                        if (verbose) {
                            error("\n");
                            error("varid: %d, ", i);
                            error("var_name: %s, ", var_name[i]);
                            error("var_type: %s, ", s_nc_type(var_type[i]));
                            error("index:");
                            for (d = 0; d < var_rank[i]; d++)
                                error(" %d", index[d]);
                            error(", expect: %g, ", expect);
                            error("got: %g", (double) value);
                        }
                    } else {
                        ++nok;
                    }
                }
            }
        }
    }
    err =  nc_close(ncid);
    IF (err != NC_NOERR)
        error("close: %s",  nc_strerror(err));
    return nok;
}

/*
 *  check all vars in file which are (text/numeric) compatible with TYPE
 */
int
check_vars_short(const char *filename, int numVars)
{
    int i, d, err, ncid, cdf_format, ndims;
    int canConvert;   /* Both text or both numeric */
    int nok = 0;      /* count of valid comparisons */
    int dimids[MAX_RANK];
    nc_type datatype;
    char name[NC_MAX_NAME];
    size_t j, length, index[MAX_RANK];
    double expect;
    short value;

    err = file_open(filename, NC_NOWRITE, &ncid);
    IF (err != NC_NOERR) error("open: %s",  nc_strerror(err));

    err =  nc_inq_format(ncid, &cdf_format);
    IF (err != NC_NOERR) error("inq_format: %s",  nc_strerror(err));

    for (i = 0; i < numVars; i++) {
        canConvert = (var_type[i] == NC_CHAR) == (NCT_SHORT == NCT_TEXT);
        if (!canConvert) continue;

        err =  nc_inq_var(ncid, i, name, &datatype, &ndims, dimids, NULL);
        IF (err != NC_NOERR)
            error("inq_var: %s",  nc_strerror(err));
        IF (strcmp(name, var_name[i]) != 0)
            error("Unexpected var_name");
        IF (datatype != var_type[i])
            error("Unexpected type");
        IF (ndims != var_rank[i])
            error("Unexpected rank");
        for (j = 0; j < ndims; j++) {
            err =  nc_inq_dim(ncid, dimids[j], 0, &length);
            IF (err != NC_NOERR)
                error("inq_dim: %s",  nc_strerror(err));
            IF (length != var_shape[i][j])
                error("Unexpected shape");
        }
        for (j = 0; j < var_nels[i]; j++) {
            err = toMixedBase(j, var_rank[i], var_shape[i], index);
            IF (err != 0) error("error in toMixedBase");
            expect = hash4(cdf_format, var_type[i], var_rank[i], index,
                           NCT_SHORT);
            err = nc_get_var1_short(ncid, i, index, &value);
            if (inRange3(cdf_format, (double)expect,datatype,NCT_SHORT) && (expect >= short_min && expect <= short_max)) {
                IF (err != NC_NOERR) {
                    error("nc_get_var1_short: %s",  nc_strerror(err));
                } else {
                    
                    IF (!equal((double)value,expect,var_type[i],NCT_SHORT)){
                        error("Var value read not that expected");
                        if (verbose) {
                            error("\n");
                            error("varid: %d, ", i);
                            error("var_name: %s, ", var_name[i]);
                            error("var_type: %s, ", s_nc_type(var_type[i]));
                            error("index:");
                            for (d = 0; d < var_rank[i]; d++)
                                error(" %d", index[d]);
                            error(", expect: %g, ", expect);
                            error("got: %g", (double) value);
                        }
                    } else {
                        ++nok;
                    }
                }
            }
        }
    }
    err =  nc_close(ncid);
    IF (err != NC_NOERR)
        error("close: %s",  nc_strerror(err));
    return nok;
}

/*
 *  check all vars in file which are (text/numeric) compatible with TYPE
 */
int
check_vars_int(const char *filename, int numVars)
{
    int i, d, err, ncid, cdf_format, ndims;
    int canConvert;   /* Both text or both numeric */
    int nok = 0;      /* count of valid comparisons */
    int dimids[MAX_RANK];
    nc_type datatype;
    char name[NC_MAX_NAME];
    size_t j, length, index[MAX_RANK];
    double expect;
    int value;

    err = file_open(filename, NC_NOWRITE, &ncid);
    IF (err != NC_NOERR) error("open: %s",  nc_strerror(err));

    err =  nc_inq_format(ncid, &cdf_format);
    IF (err != NC_NOERR) error("inq_format: %s",  nc_strerror(err));

    for (i = 0; i < numVars; i++) {
        canConvert = (var_type[i] == NC_CHAR) == (NCT_INT == NCT_TEXT);
        if (!canConvert) continue;

        err =  nc_inq_var(ncid, i, name, &datatype, &ndims, dimids, NULL);
        IF (err != NC_NOERR)
            error("inq_var: %s",  nc_strerror(err));
        IF (strcmp(name, var_name[i]) != 0)
            error("Unexpected var_name");
        IF (datatype != var_type[i])
            error("Unexpected type");
        IF (ndims != var_rank[i])
            error("Unexpected rank");
        for (j = 0; j < ndims; j++) {
            err =  nc_inq_dim(ncid, dimids[j], 0, &length);
            IF (err != NC_NOERR)
                error("inq_dim: %s",  nc_strerror(err));
            IF (length != var_shape[i][j])
                error("Unexpected shape");
        }
        for (j = 0; j < var_nels[i]; j++) {
            err = toMixedBase(j, var_rank[i], var_shape[i], index);
            IF (err != 0) error("error in toMixedBase");
            expect = hash4(cdf_format, var_type[i], var_rank[i], index,
                           NCT_INT);
            err = nc_get_var1_int(ncid, i, index, &value);
            if (inRange3(cdf_format, (double)expect,datatype,NCT_INT) && (expect >= int_min && expect <= int_max)) {
                IF (err != NC_NOERR) {
                    error("nc_get_var1_int: %s",  nc_strerror(err));
                } else {
                    
                    IF (!equal((double)value,expect,var_type[i],NCT_INT)){
                        error("Var value read not that expected");
                        if (verbose) {
                            error("\n");
                            error("varid: %d, ", i);
                            error("var_name: %s, ", var_name[i]);
                            error("var_type: %s, ", s_nc_type(var_type[i]));
                            error("index:");
                            for (d = 0; d < var_rank[i]; d++)
                                error(" %d", index[d]);
                            error(", expect: %g, ", expect);
                            error("got: %g", (double) value);
                        }
                    } else {
                        ++nok;
                    }
                }
            }
        }
    }
    err =  nc_close(ncid);
    IF (err != NC_NOERR)
        error("close: %s",  nc_strerror(err));
    return nok;
}

/*
 *  check all vars in file which are (text/numeric) compatible with TYPE
 */
int
check_vars_long(const char *filename, int numVars)
{
    int i, d, err, ncid, cdf_format, ndims;
    int canConvert;   /* Both text or both numeric */
    int nok = 0;      /* count of valid comparisons */
    int dimids[MAX_RANK];
    nc_type datatype;
    char name[NC_MAX_NAME];
    size_t j, length, index[MAX_RANK];
    double expect;
    long value;

    err = file_open(filename, NC_NOWRITE, &ncid);
    IF (err != NC_NOERR) error("open: %s",  nc_strerror(err));

    err =  nc_inq_format(ncid, &cdf_format);
    IF (err != NC_NOERR) error("inq_format: %s",  nc_strerror(err));

    for (i = 0; i < numVars; i++) {
        canConvert = (var_type[i] == NC_CHAR) == (NCT_LONG == NCT_TEXT);
        if (!canConvert) continue;

        err =  nc_inq_var(ncid, i, name, &datatype, &ndims, dimids, NULL);
        IF (err != NC_NOERR)
            error("inq_var: %s",  nc_strerror(err));
        IF (strcmp(name, var_name[i]) != 0)
            error("Unexpected var_name");
        IF (datatype != var_type[i])
            error("Unexpected type");
        IF (ndims != var_rank[i])
            error("Unexpected rank");
        for (j = 0; j < ndims; j++) {
            err =  nc_inq_dim(ncid, dimids[j], 0, &length);
            IF (err != NC_NOERR)
                error("inq_dim: %s",  nc_strerror(err));
            IF (length != var_shape[i][j])
                error("Unexpected shape");
        }
        for (j = 0; j < var_nels[i]; j++) {
            err = toMixedBase(j, var_rank[i], var_shape[i], index);
            IF (err != 0) error("error in toMixedBase");
            expect = hash4(cdf_format, var_type[i], var_rank[i], index,
                           NCT_LONG);
            err = nc_get_var1_long(ncid, i, index, &value);
            if (inRange3(cdf_format, (double)expect,datatype,NCT_LONG) && (expect >= long_min && expect <= long_max)) {
                IF (err != NC_NOERR) {
                    error("nc_get_var1_long: %s",  nc_strerror(err));
                } else {
                    
                    IF (!equal((double)value,expect,var_type[i],NCT_LONG)){
                        error("Var value read not that expected");
                        if (verbose) {
                            error("\n");
                            error("varid: %d, ", i);
                            error("var_name: %s, ", var_name[i]);
                            error("var_type: %s, ", s_nc_type(var_type[i]));
                            error("index:");
                            for (d = 0; d < var_rank[i]; d++)
                                error(" %d", index[d]);
                            error(", expect: %g, ", expect);
                            error("got: %g", (double) value);
                        }
                    } else {
                        ++nok;
                    }
                }
            }
        }
    }
    err =  nc_close(ncid);
    IF (err != NC_NOERR)
        error("close: %s",  nc_strerror(err));
    return nok;
}

/*
 *  check all vars in file which are (text/numeric) compatible with TYPE
 */
int
check_vars_float(const char *filename, int numVars)
{
    int i, d, err, ncid, cdf_format, ndims;
    int canConvert;   /* Both text or both numeric */
    int nok = 0;      /* count of valid comparisons */
    int dimids[MAX_RANK];
    nc_type datatype;
    char name[NC_MAX_NAME];
    size_t j, length, index[MAX_RANK];
    double expect;
    float value;

    err = file_open(filename, NC_NOWRITE, &ncid);
    IF (err != NC_NOERR) error("open: %s",  nc_strerror(err));

    err =  nc_inq_format(ncid, &cdf_format);
    IF (err != NC_NOERR) error("inq_format: %s",  nc_strerror(err));

    for (i = 0; i < numVars; i++) {
        canConvert = (var_type[i] == NC_CHAR) == (NCT_FLOAT == NCT_TEXT);
        if (!canConvert) continue;

        err =  nc_inq_var(ncid, i, name, &datatype, &ndims, dimids, NULL);
        IF (err != NC_NOERR)
            error("inq_var: %s",  nc_strerror(err));
        IF (strcmp(name, var_name[i]) != 0)
            error("Unexpected var_name");
        IF (datatype != var_type[i])
            error("Unexpected type");
        IF (ndims != var_rank[i])
            error("Unexpected rank");
        for (j = 0; j < ndims; j++) {
            err =  nc_inq_dim(ncid, dimids[j], 0, &length);
            IF (err != NC_NOERR)
                error("inq_dim: %s",  nc_strerror(err));
            IF (length != var_shape[i][j])
                error("Unexpected shape");
        }
        for (j = 0; j < var_nels[i]; j++) {
            err = toMixedBase(j, var_rank[i], var_shape[i], index);
            IF (err != 0) error("error in toMixedBase");
            expect = hash4(cdf_format, var_type[i], var_rank[i], index,
                           NCT_FLOAT);
            err = nc_get_var1_float(ncid, i, index, &value);
            if (inRange3(cdf_format, (double)expect,datatype,NCT_FLOAT) && (expect >= float_min && expect <= float_max)) {
                IF (err != NC_NOERR) {
                    error("nc_get_var1_float: %s",  nc_strerror(err));
                } else {
                    
                    IF (!equal((double)value,expect,var_type[i],NCT_FLOAT)){
                        error("Var value read not that expected");
                        if (verbose) {
                            error("\n");
                            error("varid: %d, ", i);
                            error("var_name: %s, ", var_name[i]);
                            error("var_type: %s, ", s_nc_type(var_type[i]));
                            error("index:");
                            for (d = 0; d < var_rank[i]; d++)
                                error(" %d", index[d]);
                            error(", expect: %g, ", expect);
                            error("got: %g", (double) value);
                        }
                    } else {
                        ++nok;
                    }
                }
            }
        }
    }
    err =  nc_close(ncid);
    IF (err != NC_NOERR)
        error("close: %s",  nc_strerror(err));
    return nok;
}

/*
 *  check all vars in file which are (text/numeric) compatible with TYPE
 */
int
check_vars_double(const char *filename, int numVars)
{
    int i, d, err, ncid, cdf_format, ndims;
    int canConvert;   /* Both text or both numeric */
    int nok = 0;      /* count of valid comparisons */
    int dimids[MAX_RANK];
    nc_type datatype;
    char name[NC_MAX_NAME];
    size_t j, length, index[MAX_RANK];
    double expect;
    double value;

    err = file_open(filename, NC_NOWRITE, &ncid);
    IF (err != NC_NOERR) error("open: %s",  nc_strerror(err));

    err =  nc_inq_format(ncid, &cdf_format);
    IF (err != NC_NOERR) error("inq_format: %s",  nc_strerror(err));

    for (i = 0; i < numVars; i++) {
        canConvert = (var_type[i] == NC_CHAR) == (NCT_DOUBLE == NCT_TEXT);
        if (!canConvert) continue;

        err =  nc_inq_var(ncid, i, name, &datatype, &ndims, dimids, NULL);
        IF (err != NC_NOERR)
            error("inq_var: %s",  nc_strerror(err));
        IF (strcmp(name, var_name[i]) != 0)
            error("Unexpected var_name");
        IF (datatype != var_type[i])
            error("Unexpected type");
        IF (ndims != var_rank[i])
            error("Unexpected rank");
        for (j = 0; j < ndims; j++) {
            err =  nc_inq_dim(ncid, dimids[j], 0, &length);
            IF (err != NC_NOERR)
                error("inq_dim: %s",  nc_strerror(err));
            IF (length != var_shape[i][j])
                error("Unexpected shape");
        }
        for (j = 0; j < var_nels[i]; j++) {
            err = toMixedBase(j, var_rank[i], var_shape[i], index);
            IF (err != 0) error("error in toMixedBase");
            expect = hash4(cdf_format, var_type[i], var_rank[i], index,
                           NCT_DOUBLE);
            err = nc_get_var1_double(ncid, i, index, &value);
            if (inRange3(cdf_format, (double)expect,datatype,NCT_DOUBLE) && (expect >= double_min && expect <= double_max)) {
                IF (err != NC_NOERR) {
                    error("nc_get_var1_double: %s",  nc_strerror(err));
                } else {
                    
                    IF (!equal((double)value,expect,var_type[i],NCT_DOUBLE)){
                        error("Var value read not that expected");
                        if (verbose) {
                            error("\n");
                            error("varid: %d, ", i);
                            error("var_name: %s, ", var_name[i]);
                            error("var_type: %s, ", s_nc_type(var_type[i]));
                            error("index:");
                            for (d = 0; d < var_rank[i]; d++)
                                error(" %d", index[d]);
                            error(", expect: %g, ", expect);
                            error("got: %g", (double) value);
                        }
                    } else {
                        ++nok;
                    }
                }
            }
        }
    }
    err =  nc_close(ncid);
    IF (err != NC_NOERR)
        error("close: %s",  nc_strerror(err));
    return nok;
}

/*
 *  check all vars in file which are (text/numeric) compatible with TYPE
 */
int
check_vars_ushort(const char *filename, int numVars)
{
    int i, d, err, ncid, cdf_format, ndims;
    int canConvert;   /* Both text or both numeric */
    int nok = 0;      /* count of valid comparisons */
    int dimids[MAX_RANK];
    nc_type datatype;
    char name[NC_MAX_NAME];
    size_t j, length, index[MAX_RANK];
    double expect;
    ushort value;

    err = file_open(filename, NC_NOWRITE, &ncid);
    IF (err != NC_NOERR) error("open: %s",  nc_strerror(err));

    err =  nc_inq_format(ncid, &cdf_format);
    IF (err != NC_NOERR) error("inq_format: %s",  nc_strerror(err));

    for (i = 0; i < numVars; i++) {
        canConvert = (var_type[i] == NC_CHAR) == (NCT_USHORT == NCT_TEXT);
        if (!canConvert) continue;

        err =  nc_inq_var(ncid, i, name, &datatype, &ndims, dimids, NULL);
        IF (err != NC_NOERR)
            error("inq_var: %s",  nc_strerror(err));
        IF (strcmp(name, var_name[i]) != 0)
            error("Unexpected var_name");
        IF (datatype != var_type[i])
            error("Unexpected type");
        IF (ndims != var_rank[i])
            error("Unexpected rank");
        for (j = 0; j < ndims; j++) {
            err =  nc_inq_dim(ncid, dimids[j], 0, &length);
            IF (err != NC_NOERR)
                error("inq_dim: %s",  nc_strerror(err));
            IF (length != var_shape[i][j])
                error("Unexpected shape");
        }
        for (j = 0; j < var_nels[i]; j++) {
            err = toMixedBase(j, var_rank[i], var_shape[i], index);
            IF (err != 0) error("error in toMixedBase");
            expect = hash4(cdf_format, var_type[i], var_rank[i], index,
                           NCT_USHORT);
            err = nc_get_var1_ushort(ncid, i, index, &value);
            if (inRange3(cdf_format, (double)expect,datatype,NCT_USHORT) && (expect >= ushort_min && expect <= ushort_max)) {
                IF (err != NC_NOERR) {
                    error("nc_get_var1_ushort: %s",  nc_strerror(err));
                } else {
                    
                    IF (!equal((double)value,expect,var_type[i],NCT_USHORT)){
                        error("Var value read not that expected");
                        if (verbose) {
                            error("\n");
                            error("varid: %d, ", i);
                            error("var_name: %s, ", var_name[i]);
                            error("var_type: %s, ", s_nc_type(var_type[i]));
                            error("index:");
                            for (d = 0; d < var_rank[i]; d++)
                                error(" %d", index[d]);
                            error(", expect: %g, ", expect);
                            error("got: %g", (double) value);
                        }
                    } else {
                        ++nok;
                    }
                }
            }
        }
    }
    err =  nc_close(ncid);
    IF (err != NC_NOERR)
        error("close: %s",  nc_strerror(err));
    return nok;
}

/*
 *  check all vars in file which are (text/numeric) compatible with TYPE
 */
int
check_vars_uint(const char *filename, int numVars)
{
    int i, d, err, ncid, cdf_format, ndims;
    int canConvert;   /* Both text or both numeric */
    int nok = 0;      /* count of valid comparisons */
    int dimids[MAX_RANK];
    nc_type datatype;
    char name[NC_MAX_NAME];
    size_t j, length, index[MAX_RANK];
    double expect;
    uint value;

    err = file_open(filename, NC_NOWRITE, &ncid);
    IF (err != NC_NOERR) error("open: %s",  nc_strerror(err));

    err =  nc_inq_format(ncid, &cdf_format);
    IF (err != NC_NOERR) error("inq_format: %s",  nc_strerror(err));

    for (i = 0; i < numVars; i++) {
        canConvert = (var_type[i] == NC_CHAR) == (NCT_UINT == NCT_TEXT);
        if (!canConvert) continue;

        err =  nc_inq_var(ncid, i, name, &datatype, &ndims, dimids, NULL);
        IF (err != NC_NOERR)
            error("inq_var: %s",  nc_strerror(err));
        IF (strcmp(name, var_name[i]) != 0)
            error("Unexpected var_name");
        IF (datatype != var_type[i])
            error("Unexpected type");
        IF (ndims != var_rank[i])
            error("Unexpected rank");
        for (j = 0; j < ndims; j++) {
            err =  nc_inq_dim(ncid, dimids[j], 0, &length);
            IF (err != NC_NOERR)
                error("inq_dim: %s",  nc_strerror(err));
            IF (length != var_shape[i][j])
                error("Unexpected shape");
        }
        for (j = 0; j < var_nels[i]; j++) {
            err = toMixedBase(j, var_rank[i], var_shape[i], index);
            IF (err != 0) error("error in toMixedBase");
            expect = hash4(cdf_format, var_type[i], var_rank[i], index,
                           NCT_UINT);
            err = nc_get_var1_uint(ncid, i, index, &value);
            if (inRange3(cdf_format, (double)expect,datatype,NCT_UINT) && (expect >= uint_min && expect <= uint_max)) {
                IF (err != NC_NOERR) {
                    error("nc_get_var1_uint: %s",  nc_strerror(err));
                } else {
                    
                    IF (!equal((double)value,expect,var_type[i],NCT_UINT)){
                        error("Var value read not that expected");
                        if (verbose) {
                            error("\n");
                            error("varid: %d, ", i);
                            error("var_name: %s, ", var_name[i]);
                            error("var_type: %s, ", s_nc_type(var_type[i]));
                            error("index:");
                            for (d = 0; d < var_rank[i]; d++)
                                error(" %d", index[d]);
                            error(", expect: %g, ", expect);
                            error("got: %g", (double) value);
                        }
                    } else {
                        ++nok;
                    }
                }
            }
        }
    }
    err =  nc_close(ncid);
    IF (err != NC_NOERR)
        error("close: %s",  nc_strerror(err));
    return nok;
}

/*
 *  check all vars in file which are (text/numeric) compatible with TYPE
 */
int
check_vars_longlong(const char *filename, int numVars)
{
    int i, d, err, ncid, cdf_format, ndims;
    int canConvert;   /* Both text or both numeric */
    int nok = 0;      /* count of valid comparisons */
    int dimids[MAX_RANK];
    nc_type datatype;
    char name[NC_MAX_NAME];
    size_t j, length, index[MAX_RANK];
    double expect;
    longlong value;

    err = file_open(filename, NC_NOWRITE, &ncid);
    IF (err != NC_NOERR) error("open: %s",  nc_strerror(err));

    err =  nc_inq_format(ncid, &cdf_format);
    IF (err != NC_NOERR) error("inq_format: %s",  nc_strerror(err));

    for (i = 0; i < numVars; i++) {
        canConvert = (var_type[i] == NC_CHAR) == (NCT_LONGLONG == NCT_TEXT);
        if (!canConvert) continue;

        err =  nc_inq_var(ncid, i, name, &datatype, &ndims, dimids, NULL);
        IF (err != NC_NOERR)
            error("inq_var: %s",  nc_strerror(err));
        IF (strcmp(name, var_name[i]) != 0)
            error("Unexpected var_name");
        IF (datatype != var_type[i])
            error("Unexpected type");
        IF (ndims != var_rank[i])
            error("Unexpected rank");
        for (j = 0; j < ndims; j++) {
            err =  nc_inq_dim(ncid, dimids[j], 0, &length);
            IF (err != NC_NOERR)
                error("inq_dim: %s",  nc_strerror(err));
            IF (length != var_shape[i][j])
                error("Unexpected shape");
        }
        for (j = 0; j < var_nels[i]; j++) {
            err = toMixedBase(j, var_rank[i], var_shape[i], index);
            IF (err != 0) error("error in toMixedBase");
            expect = hash4(cdf_format, var_type[i], var_rank[i], index,
                           NCT_LONGLONG);
            err = nc_get_var1_longlong(ncid, i, index, &value);
            if (inRange3(cdf_format, (double)expect,datatype,NCT_LONGLONG) && (expect >= longlong_min && expect <= longlong_max)) {
                IF (err != NC_NOERR) {
                    error("nc_get_var1_longlong: %s",  nc_strerror(err));
                } else {
                    
                    IF (!equal((double)value,expect,var_type[i],NCT_LONGLONG)){
                        error("Var value read not that expected");
                        if (verbose) {
                            error("\n");
                            error("varid: %d, ", i);
                            error("var_name: %s, ", var_name[i]);
                            error("var_type: %s, ", s_nc_type(var_type[i]));
                            error("index:");
                            for (d = 0; d < var_rank[i]; d++)
                                error(" %d", index[d]);
                            error(", expect: %g, ", expect);
                            error("got: %g", (double) value);
                        }
                    } else {
                        ++nok;
                    }
                }
            }
        }
    }
    err =  nc_close(ncid);
    IF (err != NC_NOERR)
        error("close: %s",  nc_strerror(err));
    return nok;
}

/*
 *  check all vars in file which are (text/numeric) compatible with TYPE
 */
int
check_vars_ulonglong(const char *filename, int numVars)
{
    int i, d, err, ncid, cdf_format, ndims;
    int canConvert;   /* Both text or both numeric */
    int nok = 0;      /* count of valid comparisons */
    int dimids[MAX_RANK];
    nc_type datatype;
    char name[NC_MAX_NAME];
    size_t j, length, index[MAX_RANK];
    double expect;
    ulonglong value;

    err = file_open(filename, NC_NOWRITE, &ncid);
    IF (err != NC_NOERR) error("open: %s",  nc_strerror(err));

    err =  nc_inq_format(ncid, &cdf_format);
    IF (err != NC_NOERR) error("inq_format: %s",  nc_strerror(err));

    for (i = 0; i < numVars; i++) {
        canConvert = (var_type[i] == NC_CHAR) == (NCT_ULONGLONG == NCT_TEXT);
        if (!canConvert) continue;

        err =  nc_inq_var(ncid, i, name, &datatype, &ndims, dimids, NULL);
        IF (err != NC_NOERR)
            error("inq_var: %s",  nc_strerror(err));
        IF (strcmp(name, var_name[i]) != 0)
            error("Unexpected var_name");
        IF (datatype != var_type[i])
            error("Unexpected type");
        IF (ndims != var_rank[i])
            error("Unexpected rank");
        for (j = 0; j < ndims; j++) {
            err =  nc_inq_dim(ncid, dimids[j], 0, &length);
            IF (err != NC_NOERR)
                error("inq_dim: %s",  nc_strerror(err));
            IF (length != var_shape[i][j])
                error("Unexpected shape");
        }
        for (j = 0; j < var_nels[i]; j++) {
            err = toMixedBase(j, var_rank[i], var_shape[i], index);
            IF (err != 0) error("error in toMixedBase");
            expect = hash4(cdf_format, var_type[i], var_rank[i], index,
                           NCT_ULONGLONG);
            err = nc_get_var1_ulonglong(ncid, i, index, &value);
            if (inRange3(cdf_format, (double)expect,datatype,NCT_ULONGLONG) && (expect >= ulonglong_min && expect <= ulonglong_max)) {
                IF (err != NC_NOERR) {
                    error("nc_get_var1_ulonglong: %s",  nc_strerror(err));
                } else {
                    
                    IF (!equal((double)value,expect,var_type[i],NCT_ULONGLONG)){
                        error("Var value read not that expected");
                        if (verbose) {
                            error("\n");
                            error("varid: %d, ", i);
                            error("var_name: %s, ", var_name[i]);
                            error("var_type: %s, ", s_nc_type(var_type[i]));
                            error("index:");
                            for (d = 0; d < var_rank[i]; d++)
                                error(" %d", index[d]);
                            error(", expect: %g, ", expect);
                            error("got: %g", (double) value);
                        }
                    } else {
                        ++nok;
                    }
                }
            }
        }
    }
    err =  nc_close(ncid);
    IF (err != NC_NOERR)
        error("close: %s",  nc_strerror(err));
    return nok;
}




/*
 *  for _text tests, check all attributes in file which are of text type
 *  Note no NC_ERANGE check for text attributes as text is not convertible to
 *  any other numerical data types (i.e. NC_ECHAR)
 *
 *  for other tests, check all numerical attributes in file against values
 *  outside range of type text
 */
int
check_atts_text(int ncid, int numGatts, int numVars)
{
    int i, j, cdf_format, err;
    int canConvert;      /* Both text or both numeric */
    int nok = 0;         /* count of valid comparisons */
    size_t k, length, ndx[1];
    nc_type datatype;
    size_t nInExtRange;  /* number values within external range */
    size_t nInIntRange;  /* number values within internal range */
    double expect[MAX_NELS];
    text value[MAX_NELS];

    err =  nc_inq_format(ncid, &cdf_format);
    IF (err != NC_NOERR)
        error("inq_format: %s",  nc_strerror(err));

    for (i = -1; i < numVars; i++) {
        for (j = 0; j < NATTS(i); j++) {
            canConvert = (ATT_TYPE(i,j) == NC_CHAR) ;
            if (!canConvert) continue;

            err =  nc_inq_att(ncid, i, ATT_NAME(i,j), &datatype, &length);
            IF (err != NC_NOERR)
                error("inq_att: %s",  nc_strerror(err));
            IF (datatype != ATT_TYPE(i,j))
                error("inq_att: unexpected type");
            IF (length != ATT_LEN(i,j))
                error("inq_att: unexpected length");
            assert(length <= MAX_NELS);
            nInIntRange = nInExtRange = 0;
            for (k = 0; k < length; k++) {
                ndx[0] = k;
                expect[k] = hash4(cdf_format, datatype, -1, ndx, NCT_TEXT);
                if (inRange3(cdf_format, expect[k], datatype, NCT_TEXT)) {
                    ++nInExtRange;
                    if (0)
                        ++nInIntRange;
                }
            }
            err =  nc_get_att_text(ncid, i, ATT_NAME(i,j), value);
            if (nInExtRange == length && nInIntRange == length) {
                IF (err != NC_NOERR)
                    error("expecting NC_NOERR but got %s",nc_err_code_name(err));
            } else {
                IF (err != NC_NOERR && err != NC_ERANGE)
                    error("expecting NC_NOERR or NC_ERANGE but got %s",nc_err_code_name(err));
            }
            for (k = 0; k < length; k++) {
                if (1) {
                    
                    IF (!equal((double)value[k],expect[k],datatype,NCT_TEXT)) {
                        error("att. value read not that expected");
                        if (verbose) {
                            error("\n");
                            error("varid: %d, ", i);
                            error("att_name: %s, ", ATT_NAME(i,j));
                            error("att_type: %s, ", s_nc_type(ATT_TYPE(i,j)));
                            error("element number: %d ", k);
                            error("expect: %g, ", expect[k]);
                            error("got: %g", (double) value[k]);
                        }
                    } else {
                        nok++;
                    }
                }
            }
        }
    }
    return nok;
}

/*
 *  for _text tests, check all attributes in file which are of text type
 *  Note no NC_ERANGE check for text attributes as text is not convertible to
 *  any other numerical data types (i.e. NC_ECHAR)
 *
 *  for other tests, check all numerical attributes in file against values
 *  outside range of type uchar
 */
int
check_atts_uchar(int ncid, int numGatts, int numVars)
{
    int i, j, cdf_format, err;
    int canConvert;      /* Both text or both numeric */
    int nok = 0;         /* count of valid comparisons */
    size_t k, length, ndx[1];
    nc_type datatype;
    size_t nInExtRange;  /* number values within external range */
    size_t nInIntRange;  /* number values within internal range */
    double expect[MAX_NELS];
    uchar value[MAX_NELS];

    err =  nc_inq_format(ncid, &cdf_format);
    IF (err != NC_NOERR)
        error("inq_format: %s",  nc_strerror(err));

    for (i = -1; i < numVars; i++) {
        for (j = 0; j < NATTS(i); j++) {
            canConvert = (ATT_TYPE(i,j) == NC_CHAR) == (NCT_UCHAR == NCT_TEXT);
            if (!canConvert) continue;

            err =  nc_inq_att(ncid, i, ATT_NAME(i,j), &datatype, &length);
            IF (err != NC_NOERR)
                error("inq_att: %s",  nc_strerror(err));
            IF (datatype != ATT_TYPE(i,j))
                error("inq_att: unexpected type");
            IF (length != ATT_LEN(i,j))
                error("inq_att: unexpected length");
            assert(length <= MAX_NELS);
            nInIntRange = nInExtRange = 0;
            for (k = 0; k < length; k++) {
                ndx[0] = k;
                expect[k] = hash4(cdf_format, datatype, -1, ndx, NCT_UCHAR);
                if (inRange3(cdf_format, expect[k], datatype, NCT_UCHAR)) {
                    ++nInExtRange;
                    if ((expect[k] >= uchar_min && expect[k] <= uchar_max))
                        ++nInIntRange;
                }
            }
            err =  nc_get_att_uchar(ncid, i, ATT_NAME(i,j), value);
            if (nInExtRange == length && nInIntRange == length) {
                IF (err != NC_NOERR)
                    error("expecting NC_NOERR but got %s",nc_err_code_name(err));
            } else {
                IF (err != NC_NOERR && err != NC_ERANGE)
                    error("expecting NC_NOERR or NC_ERANGE but got %s",nc_err_code_name(err));
            }
            for (k = 0; k < length; k++) {
                if (inRange3(cdf_format, (double)expect[k],datatype,NCT_UCHAR) && (expect[k] >= uchar_min && expect[k] <= uchar_max)) {
                    
                    /* In put_vars(), nc_put_vara_double() is used to write
                     * variables of type NC_BYTE to files. For uchar APIs,
                     * NC_BYTE variables are treated as unsigned for CDF-1 and 2
                     * formats. Thus, we skip the equal test for out-of-bound
                     * values below for uchar APIs.
                     */
                    if (cdf_format < NC_FORMAT_CDF5 &&
                        ATT_TYPE(i,j) == NC_BYTE && expect[k] > schar_max)
                        continue;
                    IF (!equal((double)value[k],expect[k],datatype,NCT_UCHAR)) {
                        error("att. value read not that expected");
                        if (verbose) {
                            error("\n");
                            error("varid: %d, ", i);
                            error("att_name: %s, ", ATT_NAME(i,j));
                            error("att_type: %s, ", s_nc_type(ATT_TYPE(i,j)));
                            error("element number: %d ", k);
                            error("expect: %g, ", expect[k]);
                            error("got: %g", (double) value[k]);
                        }
                    } else {
                        nok++;
                    }
                }
            }
        }
    }
    return nok;
}

/*
 *  for _text tests, check all attributes in file which are of text type
 *  Note no NC_ERANGE check for text attributes as text is not convertible to
 *  any other numerical data types (i.e. NC_ECHAR)
 *
 *  for other tests, check all numerical attributes in file against values
 *  outside range of type schar
 */
int
check_atts_schar(int ncid, int numGatts, int numVars)
{
    int i, j, cdf_format, err;
    int canConvert;      /* Both text or both numeric */
    int nok = 0;         /* count of valid comparisons */
    size_t k, length, ndx[1];
    nc_type datatype;
    size_t nInExtRange;  /* number values within external range */
    size_t nInIntRange;  /* number values within internal range */
    double expect[MAX_NELS];
    schar value[MAX_NELS];

    err =  nc_inq_format(ncid, &cdf_format);
    IF (err != NC_NOERR)
        error("inq_format: %s",  nc_strerror(err));

    for (i = -1; i < numVars; i++) {
        for (j = 0; j < NATTS(i); j++) {
            canConvert = (ATT_TYPE(i,j) == NC_CHAR) == (NCT_SCHAR == NCT_TEXT);
            if (!canConvert) continue;

            err =  nc_inq_att(ncid, i, ATT_NAME(i,j), &datatype, &length);
            IF (err != NC_NOERR)
                error("inq_att: %s",  nc_strerror(err));
            IF (datatype != ATT_TYPE(i,j))
                error("inq_att: unexpected type");
            IF (length != ATT_LEN(i,j))
                error("inq_att: unexpected length");
            assert(length <= MAX_NELS);
            nInIntRange = nInExtRange = 0;
            for (k = 0; k < length; k++) {
                ndx[0] = k;
                expect[k] = hash4(cdf_format, datatype, -1, ndx, NCT_SCHAR);
                if (inRange3(cdf_format, expect[k], datatype, NCT_SCHAR)) {
                    ++nInExtRange;
                    if ((expect[k] >= schar_min && expect[k] <= schar_max))
                        ++nInIntRange;
                }
            }
            err =  nc_get_att_schar(ncid, i, ATT_NAME(i,j), value);
            if (nInExtRange == length && nInIntRange == length) {
                IF (err != NC_NOERR)
                    error("expecting NC_NOERR but got %s",nc_err_code_name(err));
            } else {
                IF (err != NC_NOERR && err != NC_ERANGE)
                    error("expecting NC_NOERR or NC_ERANGE but got %s",nc_err_code_name(err));
            }
            for (k = 0; k < length; k++) {
                if (inRange3(cdf_format, (double)expect[k],datatype,NCT_SCHAR) && (expect[k] >= schar_min && expect[k] <= schar_max)) {
                    
                    IF (!equal((double)value[k],expect[k],datatype,NCT_SCHAR)) {
                        error("att. value read not that expected");
                        if (verbose) {
                            error("\n");
                            error("varid: %d, ", i);
                            error("att_name: %s, ", ATT_NAME(i,j));
                            error("att_type: %s, ", s_nc_type(ATT_TYPE(i,j)));
                            error("element number: %d ", k);
                            error("expect: %g, ", expect[k]);
                            error("got: %g", (double) value[k]);
                        }
                    } else {
                        nok++;
                    }
                }
            }
        }
    }
    return nok;
}

/*
 *  for _text tests, check all attributes in file which are of text type
 *  Note no NC_ERANGE check for text attributes as text is not convertible to
 *  any other numerical data types (i.e. NC_ECHAR)
 *
 *  for other tests, check all numerical attributes in file against values
 *  outside range of type short
 */
int
check_atts_short(int ncid, int numGatts, int numVars)
{
    int i, j, cdf_format, err;
    int canConvert;      /* Both text or both numeric */
    int nok = 0;         /* count of valid comparisons */
    size_t k, length, ndx[1];
    nc_type datatype;
    size_t nInExtRange;  /* number values within external range */
    size_t nInIntRange;  /* number values within internal range */
    double expect[MAX_NELS];
    short value[MAX_NELS];

    err =  nc_inq_format(ncid, &cdf_format);
    IF (err != NC_NOERR)
        error("inq_format: %s",  nc_strerror(err));

    for (i = -1; i < numVars; i++) {
        for (j = 0; j < NATTS(i); j++) {
            canConvert = (ATT_TYPE(i,j) == NC_CHAR) == (NCT_SHORT == NCT_TEXT);
            if (!canConvert) continue;

            err =  nc_inq_att(ncid, i, ATT_NAME(i,j), &datatype, &length);
            IF (err != NC_NOERR)
                error("inq_att: %s",  nc_strerror(err));
            IF (datatype != ATT_TYPE(i,j))
                error("inq_att: unexpected type");
            IF (length != ATT_LEN(i,j))
                error("inq_att: unexpected length");
            assert(length <= MAX_NELS);
            nInIntRange = nInExtRange = 0;
            for (k = 0; k < length; k++) {
                ndx[0] = k;
                expect[k] = hash4(cdf_format, datatype, -1, ndx, NCT_SHORT);
                if (inRange3(cdf_format, expect[k], datatype, NCT_SHORT)) {
                    ++nInExtRange;
                    if ((expect[k] >= short_min && expect[k] <= short_max))
                        ++nInIntRange;
                }
            }
            err =  nc_get_att_short(ncid, i, ATT_NAME(i,j), value);
            if (nInExtRange == length && nInIntRange == length) {
                IF (err != NC_NOERR)
                    error("expecting NC_NOERR but got %s",nc_err_code_name(err));
            } else {
                IF (err != NC_NOERR && err != NC_ERANGE)
                    error("expecting NC_NOERR or NC_ERANGE but got %s",nc_err_code_name(err));
            }
            for (k = 0; k < length; k++) {
                if (inRange3(cdf_format, (double)expect[k],datatype,NCT_SHORT) && (expect[k] >= short_min && expect[k] <= short_max)) {
                    
                    IF (!equal((double)value[k],expect[k],datatype,NCT_SHORT)) {
                        error("att. value read not that expected");
                        if (verbose) {
                            error("\n");
                            error("varid: %d, ", i);
                            error("att_name: %s, ", ATT_NAME(i,j));
                            error("att_type: %s, ", s_nc_type(ATT_TYPE(i,j)));
                            error("element number: %d ", k);
                            error("expect: %g, ", expect[k]);
                            error("got: %g", (double) value[k]);
                        }
                    } else {
                        nok++;
                    }
                }
            }
        }
    }
    return nok;
}

/*
 *  for _text tests, check all attributes in file which are of text type
 *  Note no NC_ERANGE check for text attributes as text is not convertible to
 *  any other numerical data types (i.e. NC_ECHAR)
 *
 *  for other tests, check all numerical attributes in file against values
 *  outside range of type int
 */
int
check_atts_int(int ncid, int numGatts, int numVars)
{
    int i, j, cdf_format, err;
    int canConvert;      /* Both text or both numeric */
    int nok = 0;         /* count of valid comparisons */
    size_t k, length, ndx[1];
    nc_type datatype;
    size_t nInExtRange;  /* number values within external range */
    size_t nInIntRange;  /* number values within internal range */
    double expect[MAX_NELS];
    int value[MAX_NELS];

    err =  nc_inq_format(ncid, &cdf_format);
    IF (err != NC_NOERR)
        error("inq_format: %s",  nc_strerror(err));

    for (i = -1; i < numVars; i++) {
        for (j = 0; j < NATTS(i); j++) {
            canConvert = (ATT_TYPE(i,j) == NC_CHAR) == (NCT_INT == NCT_TEXT);
            if (!canConvert) continue;

            err =  nc_inq_att(ncid, i, ATT_NAME(i,j), &datatype, &length);
            IF (err != NC_NOERR)
                error("inq_att: %s",  nc_strerror(err));
            IF (datatype != ATT_TYPE(i,j))
                error("inq_att: unexpected type");
            IF (length != ATT_LEN(i,j))
                error("inq_att: unexpected length");
            assert(length <= MAX_NELS);
            nInIntRange = nInExtRange = 0;
            for (k = 0; k < length; k++) {
                ndx[0] = k;
                expect[k] = hash4(cdf_format, datatype, -1, ndx, NCT_INT);
                if (inRange3(cdf_format, expect[k], datatype, NCT_INT)) {
                    ++nInExtRange;
                    if ((expect[k] >= int_min && expect[k] <= int_max))
                        ++nInIntRange;
                }
            }
            err =  nc_get_att_int(ncid, i, ATT_NAME(i,j), value);
            if (nInExtRange == length && nInIntRange == length) {
                IF (err != NC_NOERR)
                    error("expecting NC_NOERR but got %s",nc_err_code_name(err));
            } else {
                IF (err != NC_NOERR && err != NC_ERANGE)
                    error("expecting NC_NOERR or NC_ERANGE but got %s",nc_err_code_name(err));
            }
            for (k = 0; k < length; k++) {
                if (inRange3(cdf_format, (double)expect[k],datatype,NCT_INT) && (expect[k] >= int_min && expect[k] <= int_max)) {
                    
                    IF (!equal((double)value[k],expect[k],datatype,NCT_INT)) {
                        error("att. value read not that expected");
                        if (verbose) {
                            error("\n");
                            error("varid: %d, ", i);
                            error("att_name: %s, ", ATT_NAME(i,j));
                            error("att_type: %s, ", s_nc_type(ATT_TYPE(i,j)));
                            error("element number: %d ", k);
                            error("expect: %g, ", expect[k]);
                            error("got: %g", (double) value[k]);
                        }
                    } else {
                        nok++;
                    }
                }
            }
        }
    }
    return nok;
}

/*
 *  for _text tests, check all attributes in file which are of text type
 *  Note no NC_ERANGE check for text attributes as text is not convertible to
 *  any other numerical data types (i.e. NC_ECHAR)
 *
 *  for other tests, check all numerical attributes in file against values
 *  outside range of type long
 */
int
check_atts_long(int ncid, int numGatts, int numVars)
{
    int i, j, cdf_format, err;
    int canConvert;      /* Both text or both numeric */
    int nok = 0;         /* count of valid comparisons */
    size_t k, length, ndx[1];
    nc_type datatype;
    size_t nInExtRange;  /* number values within external range */
    size_t nInIntRange;  /* number values within internal range */
    double expect[MAX_NELS];
    long value[MAX_NELS];

    err =  nc_inq_format(ncid, &cdf_format);
    IF (err != NC_NOERR)
        error("inq_format: %s",  nc_strerror(err));

    for (i = -1; i < numVars; i++) {
        for (j = 0; j < NATTS(i); j++) {
            canConvert = (ATT_TYPE(i,j) == NC_CHAR) == (NCT_LONG == NCT_TEXT);
            if (!canConvert) continue;

            err =  nc_inq_att(ncid, i, ATT_NAME(i,j), &datatype, &length);
            IF (err != NC_NOERR)
                error("inq_att: %s",  nc_strerror(err));
            IF (datatype != ATT_TYPE(i,j))
                error("inq_att: unexpected type");
            IF (length != ATT_LEN(i,j))
                error("inq_att: unexpected length");
            assert(length <= MAX_NELS);
            nInIntRange = nInExtRange = 0;
            for (k = 0; k < length; k++) {
                ndx[0] = k;
                expect[k] = hash4(cdf_format, datatype, -1, ndx, NCT_LONG);
                if (inRange3(cdf_format, expect[k], datatype, NCT_LONG)) {
                    ++nInExtRange;
                    if ((expect[k] >= long_min && expect[k] <= long_max))
                        ++nInIntRange;
                }
            }
            err =  nc_get_att_long(ncid, i, ATT_NAME(i,j), value);
            if (nInExtRange == length && nInIntRange == length) {
                IF (err != NC_NOERR)
                    error("expecting NC_NOERR but got %s",nc_err_code_name(err));
            } else {
                IF (err != NC_NOERR && err != NC_ERANGE)
                    error("expecting NC_NOERR or NC_ERANGE but got %s",nc_err_code_name(err));
            }
            for (k = 0; k < length; k++) {
                if (inRange3(cdf_format, (double)expect[k],datatype,NCT_LONG) && (expect[k] >= long_min && expect[k] <= long_max)) {
                    
                    IF (!equal((double)value[k],expect[k],datatype,NCT_LONG)) {
                        error("att. value read not that expected");
                        if (verbose) {
                            error("\n");
                            error("varid: %d, ", i);
                            error("att_name: %s, ", ATT_NAME(i,j));
                            error("att_type: %s, ", s_nc_type(ATT_TYPE(i,j)));
                            error("element number: %d ", k);
                            error("expect: %g, ", expect[k]);
                            error("got: %g", (double) value[k]);
                        }
                    } else {
                        nok++;
                    }
                }
            }
        }
    }
    return nok;
}

/*
 *  for _text tests, check all attributes in file which are of text type
 *  Note no NC_ERANGE check for text attributes as text is not convertible to
 *  any other numerical data types (i.e. NC_ECHAR)
 *
 *  for other tests, check all numerical attributes in file against values
 *  outside range of type float
 */
int
check_atts_float(int ncid, int numGatts, int numVars)
{
    int i, j, cdf_format, err;
    int canConvert;      /* Both text or both numeric */
    int nok = 0;         /* count of valid comparisons */
    size_t k, length, ndx[1];
    nc_type datatype;
    size_t nInExtRange;  /* number values within external range */
    size_t nInIntRange;  /* number values within internal range */
    double expect[MAX_NELS];
    float value[MAX_NELS];

    err =  nc_inq_format(ncid, &cdf_format);
    IF (err != NC_NOERR)
        error("inq_format: %s",  nc_strerror(err));

    for (i = -1; i < numVars; i++) {
        for (j = 0; j < NATTS(i); j++) {
            canConvert = (ATT_TYPE(i,j) == NC_CHAR) == (NCT_FLOAT == NCT_TEXT);
            if (!canConvert) continue;

            err =  nc_inq_att(ncid, i, ATT_NAME(i,j), &datatype, &length);
            IF (err != NC_NOERR)
                error("inq_att: %s",  nc_strerror(err));
            IF (datatype != ATT_TYPE(i,j))
                error("inq_att: unexpected type");
            IF (length != ATT_LEN(i,j))
                error("inq_att: unexpected length");
            assert(length <= MAX_NELS);
            nInIntRange = nInExtRange = 0;
            for (k = 0; k < length; k++) {
                ndx[0] = k;
                expect[k] = hash4(cdf_format, datatype, -1, ndx, NCT_FLOAT);
                if (inRange3(cdf_format, expect[k], datatype, NCT_FLOAT)) {
                    ++nInExtRange;
                    if ((expect[k] >= float_min && expect[k] <= float_max))
                        ++nInIntRange;
                }
            }
            err =  nc_get_att_float(ncid, i, ATT_NAME(i,j), value);
            if (nInExtRange == length && nInIntRange == length) {
                IF (err != NC_NOERR)
                    error("expecting NC_NOERR but got %s",nc_err_code_name(err));
            } else {
                IF (err != NC_NOERR && err != NC_ERANGE)
                    error("expecting NC_NOERR or NC_ERANGE but got %s",nc_err_code_name(err));
            }
            for (k = 0; k < length; k++) {
                if (inRange3(cdf_format, (double)expect[k],datatype,NCT_FLOAT) && (expect[k] >= float_min && expect[k] <= float_max)) {
                    
                    IF (!equal((double)value[k],expect[k],datatype,NCT_FLOAT)) {
                        error("att. value read not that expected");
                        if (verbose) {
                            error("\n");
                            error("varid: %d, ", i);
                            error("att_name: %s, ", ATT_NAME(i,j));
                            error("att_type: %s, ", s_nc_type(ATT_TYPE(i,j)));
                            error("element number: %d ", k);
                            error("expect: %g, ", expect[k]);
                            error("got: %g", (double) value[k]);
                        }
                    } else {
                        nok++;
                    }
                }
            }
        }
    }
    return nok;
}

/*
 *  for _text tests, check all attributes in file which are of text type
 *  Note no NC_ERANGE check for text attributes as text is not convertible to
 *  any other numerical data types (i.e. NC_ECHAR)
 *
 *  for other tests, check all numerical attributes in file against values
 *  outside range of type double
 */
int
check_atts_double(int ncid, int numGatts, int numVars)
{
    int i, j, cdf_format, err;
    int canConvert;      /* Both text or both numeric */
    int nok = 0;         /* count of valid comparisons */
    size_t k, length, ndx[1];
    nc_type datatype;
    size_t nInExtRange;  /* number values within external range */
    size_t nInIntRange;  /* number values within internal range */
    double expect[MAX_NELS];
    double value[MAX_NELS];

    err =  nc_inq_format(ncid, &cdf_format);
    IF (err != NC_NOERR)
        error("inq_format: %s",  nc_strerror(err));

    for (i = -1; i < numVars; i++) {
        for (j = 0; j < NATTS(i); j++) {
            canConvert = (ATT_TYPE(i,j) == NC_CHAR) == (NCT_DOUBLE == NCT_TEXT);
            if (!canConvert) continue;

            err =  nc_inq_att(ncid, i, ATT_NAME(i,j), &datatype, &length);
            IF (err != NC_NOERR)
                error("inq_att: %s",  nc_strerror(err));
            IF (datatype != ATT_TYPE(i,j))
                error("inq_att: unexpected type");
            IF (length != ATT_LEN(i,j))
                error("inq_att: unexpected length");
            assert(length <= MAX_NELS);
            nInIntRange = nInExtRange = 0;
            for (k = 0; k < length; k++) {
                ndx[0] = k;
                expect[k] = hash4(cdf_format, datatype, -1, ndx, NCT_DOUBLE);
                if (inRange3(cdf_format, expect[k], datatype, NCT_DOUBLE)) {
                    ++nInExtRange;
                    if ((expect[k] >= double_min && expect[k] <= double_max))
                        ++nInIntRange;
                }
            }
            err =  nc_get_att_double(ncid, i, ATT_NAME(i,j), value);
            if (nInExtRange == length && nInIntRange == length) {
                IF (err != NC_NOERR)
                    error("expecting NC_NOERR but got %s",nc_err_code_name(err));
            } else {
                IF (err != NC_NOERR && err != NC_ERANGE)
                    error("expecting NC_NOERR or NC_ERANGE but got %s",nc_err_code_name(err));
            }
            for (k = 0; k < length; k++) {
                if (inRange3(cdf_format, (double)expect[k],datatype,NCT_DOUBLE) && (expect[k] >= double_min && expect[k] <= double_max)) {
                    
                    IF (!equal((double)value[k],expect[k],datatype,NCT_DOUBLE)) {
                        error("att. value read not that expected");
                        if (verbose) {
                            error("\n");
                            error("varid: %d, ", i);
                            error("att_name: %s, ", ATT_NAME(i,j));
                            error("att_type: %s, ", s_nc_type(ATT_TYPE(i,j)));
                            error("element number: %d ", k);
                            error("expect: %g, ", expect[k]);
                            error("got: %g", (double) value[k]);
                        }
                    } else {
                        nok++;
                    }
                }
            }
        }
    }
    return nok;
}

/*
 *  for _text tests, check all attributes in file which are of text type
 *  Note no NC_ERANGE check for text attributes as text is not convertible to
 *  any other numerical data types (i.e. NC_ECHAR)
 *
 *  for other tests, check all numerical attributes in file against values
 *  outside range of type ushort
 */
int
check_atts_ushort(int ncid, int numGatts, int numVars)
{
    int i, j, cdf_format, err;
    int canConvert;      /* Both text or both numeric */
    int nok = 0;         /* count of valid comparisons */
    size_t k, length, ndx[1];
    nc_type datatype;
    size_t nInExtRange;  /* number values within external range */
    size_t nInIntRange;  /* number values within internal range */
    double expect[MAX_NELS];
    ushort value[MAX_NELS];

    err =  nc_inq_format(ncid, &cdf_format);
    IF (err != NC_NOERR)
        error("inq_format: %s",  nc_strerror(err));

    for (i = -1; i < numVars; i++) {
        for (j = 0; j < NATTS(i); j++) {
            canConvert = (ATT_TYPE(i,j) == NC_CHAR) == (NCT_USHORT == NCT_TEXT);
            if (!canConvert) continue;

            err =  nc_inq_att(ncid, i, ATT_NAME(i,j), &datatype, &length);
            IF (err != NC_NOERR)
                error("inq_att: %s",  nc_strerror(err));
            IF (datatype != ATT_TYPE(i,j))
                error("inq_att: unexpected type");
            IF (length != ATT_LEN(i,j))
                error("inq_att: unexpected length");
            assert(length <= MAX_NELS);
            nInIntRange = nInExtRange = 0;
            for (k = 0; k < length; k++) {
                ndx[0] = k;
                expect[k] = hash4(cdf_format, datatype, -1, ndx, NCT_USHORT);
                if (inRange3(cdf_format, expect[k], datatype, NCT_USHORT)) {
                    ++nInExtRange;
                    if ((expect[k] >= ushort_min && expect[k] <= ushort_max))
                        ++nInIntRange;
                }
            }
            err =  nc_get_att_ushort(ncid, i, ATT_NAME(i,j), value);
            if (nInExtRange == length && nInIntRange == length) {
                IF (err != NC_NOERR)
                    error("expecting NC_NOERR but got %s",nc_err_code_name(err));
            } else {
                IF (err != NC_NOERR && err != NC_ERANGE)
                    error("expecting NC_NOERR or NC_ERANGE but got %s",nc_err_code_name(err));
            }
            for (k = 0; k < length; k++) {
                if (inRange3(cdf_format, (double)expect[k],datatype,NCT_USHORT) && (expect[k] >= ushort_min && expect[k] <= ushort_max)) {
                    
                    IF (!equal((double)value[k],expect[k],datatype,NCT_USHORT)) {
                        error("att. value read not that expected");
                        if (verbose) {
                            error("\n");
                            error("varid: %d, ", i);
                            error("att_name: %s, ", ATT_NAME(i,j));
                            error("att_type: %s, ", s_nc_type(ATT_TYPE(i,j)));
                            error("element number: %d ", k);
                            error("expect: %g, ", expect[k]);
                            error("got: %g", (double) value[k]);
                        }
                    } else {
                        nok++;
                    }
                }
            }
        }
    }
    return nok;
}

/*
 *  for _text tests, check all attributes in file which are of text type
 *  Note no NC_ERANGE check for text attributes as text is not convertible to
 *  any other numerical data types (i.e. NC_ECHAR)
 *
 *  for other tests, check all numerical attributes in file against values
 *  outside range of type uint
 */
int
check_atts_uint(int ncid, int numGatts, int numVars)
{
    int i, j, cdf_format, err;
    int canConvert;      /* Both text or both numeric */
    int nok = 0;         /* count of valid comparisons */
    size_t k, length, ndx[1];
    nc_type datatype;
    size_t nInExtRange;  /* number values within external range */
    size_t nInIntRange;  /* number values within internal range */
    double expect[MAX_NELS];
    uint value[MAX_NELS];

    err =  nc_inq_format(ncid, &cdf_format);
    IF (err != NC_NOERR)
        error("inq_format: %s",  nc_strerror(err));

    for (i = -1; i < numVars; i++) {
        for (j = 0; j < NATTS(i); j++) {
            canConvert = (ATT_TYPE(i,j) == NC_CHAR) == (NCT_UINT == NCT_TEXT);
            if (!canConvert) continue;

            err =  nc_inq_att(ncid, i, ATT_NAME(i,j), &datatype, &length);
            IF (err != NC_NOERR)
                error("inq_att: %s",  nc_strerror(err));
            IF (datatype != ATT_TYPE(i,j))
                error("inq_att: unexpected type");
            IF (length != ATT_LEN(i,j))
                error("inq_att: unexpected length");
            assert(length <= MAX_NELS);
            nInIntRange = nInExtRange = 0;
            for (k = 0; k < length; k++) {
                ndx[0] = k;
                expect[k] = hash4(cdf_format, datatype, -1, ndx, NCT_UINT);
                if (inRange3(cdf_format, expect[k], datatype, NCT_UINT)) {
                    ++nInExtRange;
                    if ((expect[k] >= uint_min && expect[k] <= uint_max))
                        ++nInIntRange;
                }
            }
            err =  nc_get_att_uint(ncid, i, ATT_NAME(i,j), value);
            if (nInExtRange == length && nInIntRange == length) {
                IF (err != NC_NOERR)
                    error("expecting NC_NOERR but got %s",nc_err_code_name(err));
            } else {
                IF (err != NC_NOERR && err != NC_ERANGE)
                    error("expecting NC_NOERR or NC_ERANGE but got %s",nc_err_code_name(err));
            }
            for (k = 0; k < length; k++) {
                if (inRange3(cdf_format, (double)expect[k],datatype,NCT_UINT) && (expect[k] >= uint_min && expect[k] <= uint_max)) {
                    
                    IF (!equal((double)value[k],expect[k],datatype,NCT_UINT)) {
                        error("att. value read not that expected");
                        if (verbose) {
                            error("\n");
                            error("varid: %d, ", i);
                            error("att_name: %s, ", ATT_NAME(i,j));
                            error("att_type: %s, ", s_nc_type(ATT_TYPE(i,j)));
                            error("element number: %d ", k);
                            error("expect: %g, ", expect[k]);
                            error("got: %g", (double) value[k]);
                        }
                    } else {
                        nok++;
                    }
                }
            }
        }
    }
    return nok;
}

/*
 *  for _text tests, check all attributes in file which are of text type
 *  Note no NC_ERANGE check for text attributes as text is not convertible to
 *  any other numerical data types (i.e. NC_ECHAR)
 *
 *  for other tests, check all numerical attributes in file against values
 *  outside range of type longlong
 */
int
check_atts_longlong(int ncid, int numGatts, int numVars)
{
    int i, j, cdf_format, err;
    int canConvert;      /* Both text or both numeric */
    int nok = 0;         /* count of valid comparisons */
    size_t k, length, ndx[1];
    nc_type datatype;
    size_t nInExtRange;  /* number values within external range */
    size_t nInIntRange;  /* number values within internal range */
    double expect[MAX_NELS];
    longlong value[MAX_NELS];

    err =  nc_inq_format(ncid, &cdf_format);
    IF (err != NC_NOERR)
        error("inq_format: %s",  nc_strerror(err));

    for (i = -1; i < numVars; i++) {
        for (j = 0; j < NATTS(i); j++) {
            canConvert = (ATT_TYPE(i,j) == NC_CHAR) == (NCT_LONGLONG == NCT_TEXT);
            if (!canConvert) continue;

            err =  nc_inq_att(ncid, i, ATT_NAME(i,j), &datatype, &length);
            IF (err != NC_NOERR)
                error("inq_att: %s",  nc_strerror(err));
            IF (datatype != ATT_TYPE(i,j))
                error("inq_att: unexpected type");
            IF (length != ATT_LEN(i,j))
                error("inq_att: unexpected length");
            assert(length <= MAX_NELS);
            nInIntRange = nInExtRange = 0;
            for (k = 0; k < length; k++) {
                ndx[0] = k;
                expect[k] = hash4(cdf_format, datatype, -1, ndx, NCT_LONGLONG);
                if (inRange3(cdf_format, expect[k], datatype, NCT_LONGLONG)) {
                    ++nInExtRange;
                    if ((expect[k] >= longlong_min && expect[k] <= longlong_max))
                        ++nInIntRange;
                }
            }
            err =  nc_get_att_longlong(ncid, i, ATT_NAME(i,j), value);
            if (nInExtRange == length && nInIntRange == length) {
                IF (err != NC_NOERR)
                    error("expecting NC_NOERR but got %s",nc_err_code_name(err));
            } else {
                IF (err != NC_NOERR && err != NC_ERANGE)
                    error("expecting NC_NOERR or NC_ERANGE but got %s",nc_err_code_name(err));
            }
            for (k = 0; k < length; k++) {
                if (inRange3(cdf_format, (double)expect[k],datatype,NCT_LONGLONG) && (expect[k] >= longlong_min && expect[k] <= longlong_max)) {
                    
                    IF (!equal((double)value[k],expect[k],datatype,NCT_LONGLONG)) {
                        error("att. value read not that expected");
                        if (verbose) {
                            error("\n");
                            error("varid: %d, ", i);
                            error("att_name: %s, ", ATT_NAME(i,j));
                            error("att_type: %s, ", s_nc_type(ATT_TYPE(i,j)));
                            error("element number: %d ", k);
                            error("expect: %g, ", expect[k]);
                            error("got: %g", (double) value[k]);
                        }
                    } else {
                        nok++;
                    }
                }
            }
        }
    }
    return nok;
}

/*
 *  for _text tests, check all attributes in file which are of text type
 *  Note no NC_ERANGE check for text attributes as text is not convertible to
 *  any other numerical data types (i.e. NC_ECHAR)
 *
 *  for other tests, check all numerical attributes in file against values
 *  outside range of type ulonglong
 */
int
check_atts_ulonglong(int ncid, int numGatts, int numVars)
{
    int i, j, cdf_format, err;
    int canConvert;      /* Both text or both numeric */
    int nok = 0;         /* count of valid comparisons */
    size_t k, length, ndx[1];
    nc_type datatype;
    size_t nInExtRange;  /* number values within external range */
    size_t nInIntRange;  /* number values within internal range */
    double expect[MAX_NELS];
    ulonglong value[MAX_NELS];

    err =  nc_inq_format(ncid, &cdf_format);
    IF (err != NC_NOERR)
        error("inq_format: %s",  nc_strerror(err));

    for (i = -1; i < numVars; i++) {
        for (j = 0; j < NATTS(i); j++) {
            canConvert = (ATT_TYPE(i,j) == NC_CHAR) == (NCT_ULONGLONG == NCT_TEXT);
            if (!canConvert) continue;

            err =  nc_inq_att(ncid, i, ATT_NAME(i,j), &datatype, &length);
            IF (err != NC_NOERR)
                error("inq_att: %s",  nc_strerror(err));
            IF (datatype != ATT_TYPE(i,j))
                error("inq_att: unexpected type");
            IF (length != ATT_LEN(i,j))
                error("inq_att: unexpected length");
            assert(length <= MAX_NELS);
            nInIntRange = nInExtRange = 0;
            for (k = 0; k < length; k++) {
                ndx[0] = k;
                expect[k] = hash4(cdf_format, datatype, -1, ndx, NCT_ULONGLONG);
                if (inRange3(cdf_format, expect[k], datatype, NCT_ULONGLONG)) {
                    ++nInExtRange;
                    if ((expect[k] >= ulonglong_min && expect[k] <= ulonglong_max))
                        ++nInIntRange;
                }
            }
            err =  nc_get_att_ulonglong(ncid, i, ATT_NAME(i,j), value);
            if (nInExtRange == length && nInIntRange == length) {
                IF (err != NC_NOERR)
                    error("expecting NC_NOERR but got %s",nc_err_code_name(err));
            } else {
                IF (err != NC_NOERR && err != NC_ERANGE)
                    error("expecting NC_NOERR or NC_ERANGE but got %s",nc_err_code_name(err));
            }
            for (k = 0; k < length; k++) {
                if (inRange3(cdf_format, (double)expect[k],datatype,NCT_ULONGLONG) && (expect[k] >= ulonglong_min && expect[k] <= ulonglong_max)) {
                    
                    IF (!equal((double)value[k],expect[k],datatype,NCT_ULONGLONG)) {
                        error("att. value read not that expected");
                        if (verbose) {
                            error("\n");
                            error("varid: %d, ", i);
                            error("att_name: %s, ", ATT_NAME(i,j));
                            error("att_type: %s, ", s_nc_type(ATT_TYPE(i,j)));
                            error("element number: %d ", k);
                            error("expect: %g, ", expect[k]);
                            error("got: %g", (double) value[k]);
                        }
                    } else {
                        nok++;
                    }
                }
            }
        }
    }
    return nok;
}




int
test_nc_put_var1_text(void)
{
    int i, err, ncid, cdf_format, nok=0;
    int canConvert;      /* Both text or both numeric */
    size_t j, index[MAX_RANK];
    text value[1];

    err = file_create(scratch, NC_CLOBBER, &ncid);
    IF (err != NC_NOERR) {
        error("create: %s",  nc_strerror(err));
        return nok;
    }

    err =  nc_inq_format(ncid, &cdf_format);
    IF (err != NC_NOERR)
        error("inq_format: %s",  nc_strerror(err));

    def_dims(ncid);
    def_vars(ncid);

    err =  nc_enddef(ncid);
    IF (err != NC_NOERR)
        error("enddef: %s",  nc_strerror(err));

    /* check if can detect a bad file ID */
    err = nc_put_var1_text(BAD_ID, 0, NULL, NULL);
    IF (err != NC_EBADID)
        error("expecting NC_EBADID but got %s",nc_err_code_name(err));
    ELSE_NOK

    /* check if can detect a bad variable ID */
    err = nc_put_var1_text(ncid, BAD_VARID, NULL, NULL);
    IF (err != NC_ENOTVAR)
        error("expecting NC_ENOTVAR but got %s",nc_err_code_name(err));
    ELSE_NOK

    for (i = 0; i < numVars; i++) {
        assert(var_rank[i] <= MAX_RANK);
        assert(var_nels[i] <= MAX_NELS);

        value[0] = 5;  /* reset to a value within bounds */

        /* check if can detect a bad file ID */
        err = nc_put_var1_text(BAD_ID, i, NULL, value);
        IF (err != NC_EBADID)
            error("expecting NC_EBADID but got %s",nc_err_code_name(err));
        ELSE_NOK

        canConvert = (var_type[i] == NC_CHAR) ;


        /* test NC_EINVALCOORDS */
        for (j = 0; j < var_rank[i]; j++) index[j] = 0;

        for (j = 0; j < var_rank[i]; j++) {
            if (var_dimid[i][j] == RECDIM) continue; /* skip record dim */
            index[j] = var_shape[i][j];     /* out of boundary check */
            err = nc_put_var1_text(ncid, i, index, value);
            if (!canConvert) {
                IF (err != NC_ECHAR)
                    error("expecting NC_ECHAR but got %s",nc_err_code_name(err));
                ELSE_NOK
                index[j] = 0;
                continue;
            }
            IF (err != NC_EINVALCOORDS)
                error("expecting NC_EINVALCOORDS but got %s",nc_err_code_name(err));
            ELSE_NOK
            index[j] = 0;
        }

        for (j = 0; j < var_nels[i]; j++) {
            err = toMixedBase(j, var_rank[i], var_shape[i], index);
            IF (err != 0) error("error in toMixedBase");
            value[0] = hash_text(cdf_format, var_type[i], var_rank[i], index,
                               NCT_TEXT);
            err = nc_put_var1_text(ncid, i, index, value);
            if (canConvert) {
                if (1) {
                    IF (err != NC_NOERR)
                        error("expecting NC_NOERR but got %s",nc_err_code_name(err));
                    ELSE_NOK
                }
                
                    else {

                        IF (err != NC_ERANGE)
                            error("expecting NC_ERANGE but got %s",nc_err_code_name(err));
                        ELSE_NOK
                    }


            } else {
                IF (err != NC_ECHAR)
                    error("expecting NC_ECHAR but got %s",nc_err_code_name(err));
                ELSE_NOK
            }
        }
    }

    err =  nc_close(ncid);
    IF (err != NC_NOERR)
        error("close: %s",  nc_strerror(err));

    nok += check_vars_text(scratch, numVars);

    err = nc_delete(scratch);
    IF (err != NC_NOERR)
        error("delete file %s failed", scratch);
    return nok;
}

int
test_nc_put_var1_uchar(void)
{
    int i, err, ncid, cdf_format, nok=0;
    int canConvert;      /* Both text or both numeric */
    size_t j, index[MAX_RANK];
    uchar value[1];

    err = file_create(scratch, NC_CLOBBER, &ncid);
    IF (err != NC_NOERR) {
        error("create: %s",  nc_strerror(err));
        return nok;
    }

    err =  nc_inq_format(ncid, &cdf_format);
    IF (err != NC_NOERR)
        error("inq_format: %s",  nc_strerror(err));

    def_dims(ncid);
    def_vars(ncid);

    err =  nc_enddef(ncid);
    IF (err != NC_NOERR)
        error("enddef: %s",  nc_strerror(err));

    /* check if can detect a bad file ID */
    err = nc_put_var1_uchar(BAD_ID, 0, NULL, NULL);
    IF (err != NC_EBADID)
        error("expecting NC_EBADID but got %s",nc_err_code_name(err));
    ELSE_NOK

    /* check if can detect a bad variable ID */
    err = nc_put_var1_uchar(ncid, BAD_VARID, NULL, NULL);
    IF (err != NC_ENOTVAR)
        error("expecting NC_ENOTVAR but got %s",nc_err_code_name(err));
    ELSE_NOK

    for (i = 0; i < numVars; i++) {
        assert(var_rank[i] <= MAX_RANK);
        assert(var_nels[i] <= MAX_NELS);

        value[0] = 5;  /* reset to a value within bounds */

        /* check if can detect a bad file ID */
        err = nc_put_var1_uchar(BAD_ID, i, NULL, value);
        IF (err != NC_EBADID)
            error("expecting NC_EBADID but got %s",nc_err_code_name(err));
        ELSE_NOK

        canConvert = (var_type[i] == NC_CHAR) == (NCT_UCHAR == NCT_TEXT);


        /* test NC_EINVALCOORDS */
        for (j = 0; j < var_rank[i]; j++) index[j] = 0;

        for (j = 0; j < var_rank[i]; j++) {
            if (var_dimid[i][j] == RECDIM) continue; /* skip record dim */
            index[j] = var_shape[i][j];     /* out of boundary check */
            err = nc_put_var1_uchar(ncid, i, index, value);
            if (!canConvert) {
                IF (err != NC_ECHAR)
                    error("expecting NC_ECHAR but got %s",nc_err_code_name(err));
                ELSE_NOK
                index[j] = 0;
                continue;
            }
            IF (err != NC_EINVALCOORDS)
                error("expecting NC_EINVALCOORDS but got %s",nc_err_code_name(err));
            ELSE_NOK
            index[j] = 0;
        }

        for (j = 0; j < var_nels[i]; j++) {
            err = toMixedBase(j, var_rank[i], var_shape[i], index);
            IF (err != 0) error("error in toMixedBase");
            value[0] = hash_uchar(cdf_format, var_type[i], var_rank[i], index,
                               NCT_UCHAR);
            err = nc_put_var1_uchar(ncid, i, index, value);
            if (canConvert) {
                if (inRange3(cdf_format, (double)value[0],var_type[i],NCT_UCHAR)) {
                    IF (err != NC_NOERR)
                        error("expecting NC_NOERR but got %s",nc_err_code_name(err));
                    ELSE_NOK
                }
                
#if !defined(USE_PNETCDF) || (PNETCDF_VERSION_MAJOR==1 && PNETCDF_VERSION_MINOR>=8)
                    else {

                        IF (err != NC_ERANGE)
                            error("expecting NC_ERANGE but got %s",nc_err_code_name(err));
                        ELSE_NOK
                    }
#endif

            } else {
                IF (err != NC_ECHAR)
                    error("expecting NC_ECHAR but got %s",nc_err_code_name(err));
                ELSE_NOK
            }
        }
    }

    err =  nc_close(ncid);
    IF (err != NC_NOERR)
        error("close: %s",  nc_strerror(err));

    nok += check_vars_uchar(scratch, numVars);

    err = nc_delete(scratch);
    IF (err != NC_NOERR)
        error("delete file %s failed", scratch);
    return nok;
}

int
test_nc_put_var1_schar(void)
{
    int i, err, ncid, cdf_format, nok=0;
    int canConvert;      /* Both text or both numeric */
    size_t j, index[MAX_RANK];
    schar value[1];

    err = file_create(scratch, NC_CLOBBER, &ncid);
    IF (err != NC_NOERR) {
        error("create: %s",  nc_strerror(err));
        return nok;
    }

    err =  nc_inq_format(ncid, &cdf_format);
    IF (err != NC_NOERR)
        error("inq_format: %s",  nc_strerror(err));

    def_dims(ncid);
    def_vars(ncid);

    err =  nc_enddef(ncid);
    IF (err != NC_NOERR)
        error("enddef: %s",  nc_strerror(err));

    /* check if can detect a bad file ID */
    err = nc_put_var1_schar(BAD_ID, 0, NULL, NULL);
    IF (err != NC_EBADID)
        error("expecting NC_EBADID but got %s",nc_err_code_name(err));
    ELSE_NOK

    /* check if can detect a bad variable ID */
    err = nc_put_var1_schar(ncid, BAD_VARID, NULL, NULL);
    IF (err != NC_ENOTVAR)
        error("expecting NC_ENOTVAR but got %s",nc_err_code_name(err));
    ELSE_NOK

    for (i = 0; i < numVars; i++) {
        assert(var_rank[i] <= MAX_RANK);
        assert(var_nels[i] <= MAX_NELS);

        value[0] = 5;  /* reset to a value within bounds */

        /* check if can detect a bad file ID */
        err = nc_put_var1_schar(BAD_ID, i, NULL, value);
        IF (err != NC_EBADID)
            error("expecting NC_EBADID but got %s",nc_err_code_name(err));
        ELSE_NOK

        canConvert = (var_type[i] == NC_CHAR) == (NCT_SCHAR == NCT_TEXT);


        /* test NC_EINVALCOORDS */
        for (j = 0; j < var_rank[i]; j++) index[j] = 0;

        for (j = 0; j < var_rank[i]; j++) {
            if (var_dimid[i][j] == RECDIM) continue; /* skip record dim */
            index[j] = var_shape[i][j];     /* out of boundary check */
            err = nc_put_var1_schar(ncid, i, index, value);
            if (!canConvert) {
                IF (err != NC_ECHAR)
                    error("expecting NC_ECHAR but got %s",nc_err_code_name(err));
                ELSE_NOK
                index[j] = 0;
                continue;
            }
            IF (err != NC_EINVALCOORDS)
                error("expecting NC_EINVALCOORDS but got %s",nc_err_code_name(err));
            ELSE_NOK
            index[j] = 0;
        }

        for (j = 0; j < var_nels[i]; j++) {
            err = toMixedBase(j, var_rank[i], var_shape[i], index);
            IF (err != 0) error("error in toMixedBase");
            value[0] = hash_schar(cdf_format, var_type[i], var_rank[i], index,
                               NCT_SCHAR);
            err = nc_put_var1_schar(ncid, i, index, value);
            if (canConvert) {
                if (inRange3(cdf_format, (double)value[0],var_type[i],NCT_SCHAR)) {
                    IF (err != NC_NOERR)
                        error("expecting NC_NOERR but got %s",nc_err_code_name(err));
                    ELSE_NOK
                }
                
#if defined(USE_PNETCDF) && PNETCDF_VERSION_MAJOR==1 && PNETCDF_VERSION_MINOR<7
                    else if (cdf_format < NC_FORMAT_CDF5) {
#else
                    else {
#endif
                        IF (err != NC_ERANGE)
                            error("expecting NC_ERANGE but got %s",nc_err_code_name(err));
                        ELSE_NOK
                    }


            } else {
                IF (err != NC_ECHAR)
                    error("expecting NC_ECHAR but got %s",nc_err_code_name(err));
                ELSE_NOK
            }
        }
    }

    err =  nc_close(ncid);
    IF (err != NC_NOERR)
        error("close: %s",  nc_strerror(err));

    nok += check_vars_schar(scratch, numVars);

    err = nc_delete(scratch);
    IF (err != NC_NOERR)
        error("delete file %s failed", scratch);
    return nok;
}

int
test_nc_put_var1_short(void)
{
    int i, err, ncid, cdf_format, nok=0;
    int canConvert;      /* Both text or both numeric */
    size_t j, index[MAX_RANK];
    short value[1];

    err = file_create(scratch, NC_CLOBBER, &ncid);
    IF (err != NC_NOERR) {
        error("create: %s",  nc_strerror(err));
        return nok;
    }

    err =  nc_inq_format(ncid, &cdf_format);
    IF (err != NC_NOERR)
        error("inq_format: %s",  nc_strerror(err));

    def_dims(ncid);
    def_vars(ncid);

    err =  nc_enddef(ncid);
    IF (err != NC_NOERR)
        error("enddef: %s",  nc_strerror(err));

    /* check if can detect a bad file ID */
    err = nc_put_var1_short(BAD_ID, 0, NULL, NULL);
    IF (err != NC_EBADID)
        error("expecting NC_EBADID but got %s",nc_err_code_name(err));
    ELSE_NOK

    /* check if can detect a bad variable ID */
    err = nc_put_var1_short(ncid, BAD_VARID, NULL, NULL);
    IF (err != NC_ENOTVAR)
        error("expecting NC_ENOTVAR but got %s",nc_err_code_name(err));
    ELSE_NOK

    for (i = 0; i < numVars; i++) {
        assert(var_rank[i] <= MAX_RANK);
        assert(var_nels[i] <= MAX_NELS);

        value[0] = 5;  /* reset to a value within bounds */

        /* check if can detect a bad file ID */
        err = nc_put_var1_short(BAD_ID, i, NULL, value);
        IF (err != NC_EBADID)
            error("expecting NC_EBADID but got %s",nc_err_code_name(err));
        ELSE_NOK

        canConvert = (var_type[i] == NC_CHAR) == (NCT_SHORT == NCT_TEXT);


        /* test NC_EINVALCOORDS */
        for (j = 0; j < var_rank[i]; j++) index[j] = 0;

        for (j = 0; j < var_rank[i]; j++) {
            if (var_dimid[i][j] == RECDIM) continue; /* skip record dim */
            index[j] = var_shape[i][j];     /* out of boundary check */
            err = nc_put_var1_short(ncid, i, index, value);
            if (!canConvert) {
                IF (err != NC_ECHAR)
                    error("expecting NC_ECHAR but got %s",nc_err_code_name(err));
                ELSE_NOK
                index[j] = 0;
                continue;
            }
            IF (err != NC_EINVALCOORDS)
                error("expecting NC_EINVALCOORDS but got %s",nc_err_code_name(err));
            ELSE_NOK
            index[j] = 0;
        }

        for (j = 0; j < var_nels[i]; j++) {
            err = toMixedBase(j, var_rank[i], var_shape[i], index);
            IF (err != 0) error("error in toMixedBase");
            value[0] = hash_short(cdf_format, var_type[i], var_rank[i], index,
                               NCT_SHORT);
            err = nc_put_var1_short(ncid, i, index, value);
            if (canConvert) {
                if (inRange3(cdf_format, (double)value[0],var_type[i],NCT_SHORT)) {
                    IF (err != NC_NOERR)
                        error("expecting NC_NOERR but got %s",nc_err_code_name(err));
                    ELSE_NOK
                }
                
                    else {

                        IF (err != NC_ERANGE)
                            error("expecting NC_ERANGE but got %s",nc_err_code_name(err));
                        ELSE_NOK
                    }


            } else {
                IF (err != NC_ECHAR)
                    error("expecting NC_ECHAR but got %s",nc_err_code_name(err));
                ELSE_NOK
            }
        }
    }

    err =  nc_close(ncid);
    IF (err != NC_NOERR)
        error("close: %s",  nc_strerror(err));

    nok += check_vars_short(scratch, numVars);

    err = nc_delete(scratch);
    IF (err != NC_NOERR)
        error("delete file %s failed", scratch);
    return nok;
}

int
test_nc_put_var1_int(void)
{
    int i, err, ncid, cdf_format, nok=0;
    int canConvert;      /* Both text or both numeric */
    size_t j, index[MAX_RANK];
    int value[1];

    err = file_create(scratch, NC_CLOBBER, &ncid);
    IF (err != NC_NOERR) {
        error("create: %s",  nc_strerror(err));
        return nok;
    }

    err =  nc_inq_format(ncid, &cdf_format);
    IF (err != NC_NOERR)
        error("inq_format: %s",  nc_strerror(err));

    def_dims(ncid);
    def_vars(ncid);

    err =  nc_enddef(ncid);
    IF (err != NC_NOERR)
        error("enddef: %s",  nc_strerror(err));

    /* check if can detect a bad file ID */
    err = nc_put_var1_int(BAD_ID, 0, NULL, NULL);
    IF (err != NC_EBADID)
        error("expecting NC_EBADID but got %s",nc_err_code_name(err));
    ELSE_NOK

    /* check if can detect a bad variable ID */
    err = nc_put_var1_int(ncid, BAD_VARID, NULL, NULL);
    IF (err != NC_ENOTVAR)
        error("expecting NC_ENOTVAR but got %s",nc_err_code_name(err));
    ELSE_NOK

    for (i = 0; i < numVars; i++) {
        assert(var_rank[i] <= MAX_RANK);
        assert(var_nels[i] <= MAX_NELS);

        value[0] = 5;  /* reset to a value within bounds */

        /* check if can detect a bad file ID */
        err = nc_put_var1_int(BAD_ID, i, NULL, value);
        IF (err != NC_EBADID)
            error("expecting NC_EBADID but got %s",nc_err_code_name(err));
        ELSE_NOK

        canConvert = (var_type[i] == NC_CHAR) == (NCT_INT == NCT_TEXT);


        /* test NC_EINVALCOORDS */
        for (j = 0; j < var_rank[i]; j++) index[j] = 0;

        for (j = 0; j < var_rank[i]; j++) {
            if (var_dimid[i][j] == RECDIM) continue; /* skip record dim */
            index[j] = var_shape[i][j];     /* out of boundary check */
            err = nc_put_var1_int(ncid, i, index, value);
            if (!canConvert) {
                IF (err != NC_ECHAR)
                    error("expecting NC_ECHAR but got %s",nc_err_code_name(err));
                ELSE_NOK
                index[j] = 0;
                continue;
            }
            IF (err != NC_EINVALCOORDS)
                error("expecting NC_EINVALCOORDS but got %s",nc_err_code_name(err));
            ELSE_NOK
            index[j] = 0;
        }

        for (j = 0; j < var_nels[i]; j++) {
            err = toMixedBase(j, var_rank[i], var_shape[i], index);
            IF (err != 0) error("error in toMixedBase");
            value[0] = hash_int(cdf_format, var_type[i], var_rank[i], index,
                               NCT_INT);
            err = nc_put_var1_int(ncid, i, index, value);
            if (canConvert) {
                if (inRange3(cdf_format, (double)value[0],var_type[i],NCT_INT)) {
                    IF (err != NC_NOERR)
                        error("expecting NC_NOERR but got %s",nc_err_code_name(err));
                    ELSE_NOK
                }
                
                    else {

                        IF (err != NC_ERANGE)
                            error("expecting NC_ERANGE but got %s",nc_err_code_name(err));
                        ELSE_NOK
                    }


            } else {
                IF (err != NC_ECHAR)
                    error("expecting NC_ECHAR but got %s",nc_err_code_name(err));
                ELSE_NOK
            }
        }
    }

    err =  nc_close(ncid);
    IF (err != NC_NOERR)
        error("close: %s",  nc_strerror(err));

    nok += check_vars_int(scratch, numVars);

    err = nc_delete(scratch);
    IF (err != NC_NOERR)
        error("delete file %s failed", scratch);
    return nok;
}

int
test_nc_put_var1_long(void)
{
    int i, err, ncid, cdf_format, nok=0;
    int canConvert;      /* Both text or both numeric */
    size_t j, index[MAX_RANK];
    long value[1];

    err = file_create(scratch, NC_CLOBBER, &ncid);
    IF (err != NC_NOERR) {
        error("create: %s",  nc_strerror(err));
        return nok;
    }

    err =  nc_inq_format(ncid, &cdf_format);
    IF (err != NC_NOERR)
        error("inq_format: %s",  nc_strerror(err));

    def_dims(ncid);
    def_vars(ncid);

    err =  nc_enddef(ncid);
    IF (err != NC_NOERR)
        error("enddef: %s",  nc_strerror(err));

    /* check if can detect a bad file ID */
    err = nc_put_var1_long(BAD_ID, 0, NULL, NULL);
    IF (err != NC_EBADID)
        error("expecting NC_EBADID but got %s",nc_err_code_name(err));
    ELSE_NOK

    /* check if can detect a bad variable ID */
    err = nc_put_var1_long(ncid, BAD_VARID, NULL, NULL);
    IF (err != NC_ENOTVAR)
        error("expecting NC_ENOTVAR but got %s",nc_err_code_name(err));
    ELSE_NOK

    for (i = 0; i < numVars; i++) {
        assert(var_rank[i] <= MAX_RANK);
        assert(var_nels[i] <= MAX_NELS);

        value[0] = 5;  /* reset to a value within bounds */

        /* check if can detect a bad file ID */
        err = nc_put_var1_long(BAD_ID, i, NULL, value);
        IF (err != NC_EBADID)
            error("expecting NC_EBADID but got %s",nc_err_code_name(err));
        ELSE_NOK

        canConvert = (var_type[i] == NC_CHAR) == (NCT_LONG == NCT_TEXT);


        /* test NC_EINVALCOORDS */
        for (j = 0; j < var_rank[i]; j++) index[j] = 0;

        for (j = 0; j < var_rank[i]; j++) {
            if (var_dimid[i][j] == RECDIM) continue; /* skip record dim */
            index[j] = var_shape[i][j];     /* out of boundary check */
            err = nc_put_var1_long(ncid, i, index, value);
            if (!canConvert) {
                IF (err != NC_ECHAR)
                    error("expecting NC_ECHAR but got %s",nc_err_code_name(err));
                ELSE_NOK
                index[j] = 0;
                continue;
            }
            IF (err != NC_EINVALCOORDS)
                error("expecting NC_EINVALCOORDS but got %s",nc_err_code_name(err));
            ELSE_NOK
            index[j] = 0;
        }

        for (j = 0; j < var_nels[i]; j++) {
            err = toMixedBase(j, var_rank[i], var_shape[i], index);
            IF (err != 0) error("error in toMixedBase");
            value[0] = hash_long(cdf_format, var_type[i], var_rank[i], index,
                               NCT_LONG);
            err = nc_put_var1_long(ncid, i, index, value);
            if (canConvert) {
                if (inRange3(cdf_format, (double)value[0],var_type[i],NCT_LONG)) {
                    IF (err != NC_NOERR)
                        error("expecting NC_NOERR but got %s",nc_err_code_name(err));
                    ELSE_NOK
                }
                
                    else {

                        IF (err != NC_ERANGE)
                            error("expecting NC_ERANGE but got %s",nc_err_code_name(err));
                        ELSE_NOK
                    }


            } else {
                IF (err != NC_ECHAR)
                    error("expecting NC_ECHAR but got %s",nc_err_code_name(err));
                ELSE_NOK
            }
        }
    }

    err =  nc_close(ncid);
    IF (err != NC_NOERR)
        error("close: %s",  nc_strerror(err));

    nok += check_vars_long(scratch, numVars);

    err = nc_delete(scratch);
    IF (err != NC_NOERR)
        error("delete file %s failed", scratch);
    return nok;
}

int
test_nc_put_var1_float(void)
{
    int i, err, ncid, cdf_format, nok=0;
    int canConvert;      /* Both text or both numeric */
    size_t j, index[MAX_RANK];
    float value[1];

    err = file_create(scratch, NC_CLOBBER, &ncid);
    IF (err != NC_NOERR) {
        error("create: %s",  nc_strerror(err));
        return nok;
    }

    err =  nc_inq_format(ncid, &cdf_format);
    IF (err != NC_NOERR)
        error("inq_format: %s",  nc_strerror(err));

    def_dims(ncid);
    def_vars(ncid);

    err =  nc_enddef(ncid);
    IF (err != NC_NOERR)
        error("enddef: %s",  nc_strerror(err));

    /* check if can detect a bad file ID */
    err = nc_put_var1_float(BAD_ID, 0, NULL, NULL);
    IF (err != NC_EBADID)
        error("expecting NC_EBADID but got %s",nc_err_code_name(err));
    ELSE_NOK

    /* check if can detect a bad variable ID */
    err = nc_put_var1_float(ncid, BAD_VARID, NULL, NULL);
    IF (err != NC_ENOTVAR)
        error("expecting NC_ENOTVAR but got %s",nc_err_code_name(err));
    ELSE_NOK

    for (i = 0; i < numVars; i++) {
        assert(var_rank[i] <= MAX_RANK);
        assert(var_nels[i] <= MAX_NELS);

        value[0] = 5;  /* reset to a value within bounds */

        /* check if can detect a bad file ID */
        err = nc_put_var1_float(BAD_ID, i, NULL, value);
        IF (err != NC_EBADID)
            error("expecting NC_EBADID but got %s",nc_err_code_name(err));
        ELSE_NOK

        canConvert = (var_type[i] == NC_CHAR) == (NCT_FLOAT == NCT_TEXT);


        /* test NC_EINVALCOORDS */
        for (j = 0; j < var_rank[i]; j++) index[j] = 0;

        for (j = 0; j < var_rank[i]; j++) {
            if (var_dimid[i][j] == RECDIM) continue; /* skip record dim */
            index[j] = var_shape[i][j];     /* out of boundary check */
            err = nc_put_var1_float(ncid, i, index, value);
            if (!canConvert) {
                IF (err != NC_ECHAR)
                    error("expecting NC_ECHAR but got %s",nc_err_code_name(err));
                ELSE_NOK
                index[j] = 0;
                continue;
            }
            IF (err != NC_EINVALCOORDS)
                error("expecting NC_EINVALCOORDS but got %s",nc_err_code_name(err));
            ELSE_NOK
            index[j] = 0;
        }

        for (j = 0; j < var_nels[i]; j++) {
            err = toMixedBase(j, var_rank[i], var_shape[i], index);
            IF (err != 0) error("error in toMixedBase");
            value[0] = hash_float(cdf_format, var_type[i], var_rank[i], index,
                               NCT_FLOAT);
            err = nc_put_var1_float(ncid, i, index, value);
            if (canConvert) {
                if (inRange3(cdf_format, (double)value[0],var_type[i],NCT_FLOAT)) {
                    IF (err != NC_NOERR)
                        error("expecting NC_NOERR but got %s",nc_err_code_name(err));
                    ELSE_NOK
                }
                
                    else {

                        IF (err != NC_ERANGE)
                            error("expecting NC_ERANGE but got %s",nc_err_code_name(err));
                        ELSE_NOK
                    }


            } else {
                IF (err != NC_ECHAR)
                    error("expecting NC_ECHAR but got %s",nc_err_code_name(err));
                ELSE_NOK
            }
        }
    }

    err =  nc_close(ncid);
    IF (err != NC_NOERR)
        error("close: %s",  nc_strerror(err));

    nok += check_vars_float(scratch, numVars);

    err = nc_delete(scratch);
    IF (err != NC_NOERR)
        error("delete file %s failed", scratch);
    return nok;
}

int
test_nc_put_var1_double(void)
{
    int i, err, ncid, cdf_format, nok=0;
    int canConvert;      /* Both text or both numeric */
    size_t j, index[MAX_RANK];
    double value[1];

    err = file_create(scratch, NC_CLOBBER, &ncid);
    IF (err != NC_NOERR) {
        error("create: %s",  nc_strerror(err));
        return nok;
    }

    err =  nc_inq_format(ncid, &cdf_format);
    IF (err != NC_NOERR)
        error("inq_format: %s",  nc_strerror(err));

    def_dims(ncid);
    def_vars(ncid);

    err =  nc_enddef(ncid);
    IF (err != NC_NOERR)
        error("enddef: %s",  nc_strerror(err));

    /* check if can detect a bad file ID */
    err = nc_put_var1_double(BAD_ID, 0, NULL, NULL);
    IF (err != NC_EBADID)
        error("expecting NC_EBADID but got %s",nc_err_code_name(err));
    ELSE_NOK

    /* check if can detect a bad variable ID */
    err = nc_put_var1_double(ncid, BAD_VARID, NULL, NULL);
    IF (err != NC_ENOTVAR)
        error("expecting NC_ENOTVAR but got %s",nc_err_code_name(err));
    ELSE_NOK

    for (i = 0; i < numVars; i++) {
        assert(var_rank[i] <= MAX_RANK);
        assert(var_nels[i] <= MAX_NELS);

        value[0] = 5;  /* reset to a value within bounds */

        /* check if can detect a bad file ID */
        err = nc_put_var1_double(BAD_ID, i, NULL, value);
        IF (err != NC_EBADID)
            error("expecting NC_EBADID but got %s",nc_err_code_name(err));
        ELSE_NOK

        canConvert = (var_type[i] == NC_CHAR) == (NCT_DOUBLE == NCT_TEXT);


        /* test NC_EINVALCOORDS */
        for (j = 0; j < var_rank[i]; j++) index[j] = 0;

        for (j = 0; j < var_rank[i]; j++) {
            if (var_dimid[i][j] == RECDIM) continue; /* skip record dim */
            index[j] = var_shape[i][j];     /* out of boundary check */
            err = nc_put_var1_double(ncid, i, index, value);
            if (!canConvert) {
                IF (err != NC_ECHAR)
                    error("expecting NC_ECHAR but got %s",nc_err_code_name(err));
                ELSE_NOK
                index[j] = 0;
                continue;
            }
            IF (err != NC_EINVALCOORDS)
                error("expecting NC_EINVALCOORDS but got %s",nc_err_code_name(err));
            ELSE_NOK
            index[j] = 0;
        }

        for (j = 0; j < var_nels[i]; j++) {
            err = toMixedBase(j, var_rank[i], var_shape[i], index);
            IF (err != 0) error("error in toMixedBase");
            value[0] = hash_double(cdf_format, var_type[i], var_rank[i], index,
                               NCT_DOUBLE);
            err = nc_put_var1_double(ncid, i, index, value);
            if (canConvert) {
                if (inRange3(cdf_format, (double)value[0],var_type[i],NCT_DOUBLE)) {
                    IF (err != NC_NOERR)
                        error("expecting NC_NOERR but got %s",nc_err_code_name(err));
                    ELSE_NOK
                }
                
                    else {

                        IF (err != NC_ERANGE)
                            error("expecting NC_ERANGE but got %s",nc_err_code_name(err));
                        ELSE_NOK
                    }


            } else {
                IF (err != NC_ECHAR)
                    error("expecting NC_ECHAR but got %s",nc_err_code_name(err));
                ELSE_NOK
            }
        }
    }

    err =  nc_close(ncid);
    IF (err != NC_NOERR)
        error("close: %s",  nc_strerror(err));

    nok += check_vars_double(scratch, numVars);

    err = nc_delete(scratch);
    IF (err != NC_NOERR)
        error("delete file %s failed", scratch);
    return nok;
}

int
test_nc_put_var1_ushort(void)
{
    int i, err, ncid, cdf_format, nok=0;
    int canConvert;      /* Both text or both numeric */
    size_t j, index[MAX_RANK];
    ushort value[1];

    err = file_create(scratch, NC_CLOBBER, &ncid);
    IF (err != NC_NOERR) {
        error("create: %s",  nc_strerror(err));
        return nok;
    }

    err =  nc_inq_format(ncid, &cdf_format);
    IF (err != NC_NOERR)
        error("inq_format: %s",  nc_strerror(err));

    def_dims(ncid);
    def_vars(ncid);

    err =  nc_enddef(ncid);
    IF (err != NC_NOERR)
        error("enddef: %s",  nc_strerror(err));

    /* check if can detect a bad file ID */
    err = nc_put_var1_ushort(BAD_ID, 0, NULL, NULL);
    IF (err != NC_EBADID)
        error("expecting NC_EBADID but got %s",nc_err_code_name(err));
    ELSE_NOK

    /* check if can detect a bad variable ID */
    err = nc_put_var1_ushort(ncid, BAD_VARID, NULL, NULL);
    IF (err != NC_ENOTVAR)
        error("expecting NC_ENOTVAR but got %s",nc_err_code_name(err));
    ELSE_NOK

    for (i = 0; i < numVars; i++) {
        assert(var_rank[i] <= MAX_RANK);
        assert(var_nels[i] <= MAX_NELS);

        value[0] = 5;  /* reset to a value within bounds */

        /* check if can detect a bad file ID */
        err = nc_put_var1_ushort(BAD_ID, i, NULL, value);
        IF (err != NC_EBADID)
            error("expecting NC_EBADID but got %s",nc_err_code_name(err));
        ELSE_NOK

        canConvert = (var_type[i] == NC_CHAR) == (NCT_USHORT == NCT_TEXT);


        /* test NC_EINVALCOORDS */
        for (j = 0; j < var_rank[i]; j++) index[j] = 0;

        for (j = 0; j < var_rank[i]; j++) {
            if (var_dimid[i][j] == RECDIM) continue; /* skip record dim */
            index[j] = var_shape[i][j];     /* out of boundary check */
            err = nc_put_var1_ushort(ncid, i, index, value);
            if (!canConvert) {
                IF (err != NC_ECHAR)
                    error("expecting NC_ECHAR but got %s",nc_err_code_name(err));
                ELSE_NOK
                index[j] = 0;
                continue;
            }
            IF (err != NC_EINVALCOORDS)
                error("expecting NC_EINVALCOORDS but got %s",nc_err_code_name(err));
            ELSE_NOK
            index[j] = 0;
        }

        for (j = 0; j < var_nels[i]; j++) {
            err = toMixedBase(j, var_rank[i], var_shape[i], index);
            IF (err != 0) error("error in toMixedBase");
            value[0] = hash_ushort(cdf_format, var_type[i], var_rank[i], index,
                               NCT_USHORT);
            err = nc_put_var1_ushort(ncid, i, index, value);
            if (canConvert) {
                if (inRange3(cdf_format, (double)value[0],var_type[i],NCT_USHORT)) {
                    IF (err != NC_NOERR)
                        error("expecting NC_NOERR but got %s",nc_err_code_name(err));
                    ELSE_NOK
                }
                
                    else {

                        IF (err != NC_ERANGE)
                            error("expecting NC_ERANGE but got %s",nc_err_code_name(err));
                        ELSE_NOK
                    }


            } else {
                IF (err != NC_ECHAR)
                    error("expecting NC_ECHAR but got %s",nc_err_code_name(err));
                ELSE_NOK
            }
        }
    }

    err =  nc_close(ncid);
    IF (err != NC_NOERR)
        error("close: %s",  nc_strerror(err));

    nok += check_vars_ushort(scratch, numVars);

    err = nc_delete(scratch);
    IF (err != NC_NOERR)
        error("delete file %s failed", scratch);
    return nok;
}

int
test_nc_put_var1_uint(void)
{
    int i, err, ncid, cdf_format, nok=0;
    int canConvert;      /* Both text or both numeric */
    size_t j, index[MAX_RANK];
    uint value[1];

    err = file_create(scratch, NC_CLOBBER, &ncid);
    IF (err != NC_NOERR) {
        error("create: %s",  nc_strerror(err));
        return nok;
    }

    err =  nc_inq_format(ncid, &cdf_format);
    IF (err != NC_NOERR)
        error("inq_format: %s",  nc_strerror(err));

    def_dims(ncid);
    def_vars(ncid);

    err =  nc_enddef(ncid);
    IF (err != NC_NOERR)
        error("enddef: %s",  nc_strerror(err));

    /* check if can detect a bad file ID */
    err = nc_put_var1_uint(BAD_ID, 0, NULL, NULL);
    IF (err != NC_EBADID)
        error("expecting NC_EBADID but got %s",nc_err_code_name(err));
    ELSE_NOK

    /* check if can detect a bad variable ID */
    err = nc_put_var1_uint(ncid, BAD_VARID, NULL, NULL);
    IF (err != NC_ENOTVAR)
        error("expecting NC_ENOTVAR but got %s",nc_err_code_name(err));
    ELSE_NOK

    for (i = 0; i < numVars; i++) {
        assert(var_rank[i] <= MAX_RANK);
        assert(var_nels[i] <= MAX_NELS);

        value[0] = 5;  /* reset to a value within bounds */

        /* check if can detect a bad file ID */
        err = nc_put_var1_uint(BAD_ID, i, NULL, value);
        IF (err != NC_EBADID)
            error("expecting NC_EBADID but got %s",nc_err_code_name(err));
        ELSE_NOK

        canConvert = (var_type[i] == NC_CHAR) == (NCT_UINT == NCT_TEXT);


        /* test NC_EINVALCOORDS */
        for (j = 0; j < var_rank[i]; j++) index[j] = 0;

        for (j = 0; j < var_rank[i]; j++) {
            if (var_dimid[i][j] == RECDIM) continue; /* skip record dim */
            index[j] = var_shape[i][j];     /* out of boundary check */
            err = nc_put_var1_uint(ncid, i, index, value);
            if (!canConvert) {
                IF (err != NC_ECHAR)
                    error("expecting NC_ECHAR but got %s",nc_err_code_name(err));
                ELSE_NOK
                index[j] = 0;
                continue;
            }
            IF (err != NC_EINVALCOORDS)
                error("expecting NC_EINVALCOORDS but got %s",nc_err_code_name(err));
            ELSE_NOK
            index[j] = 0;
        }

        for (j = 0; j < var_nels[i]; j++) {
            err = toMixedBase(j, var_rank[i], var_shape[i], index);
            IF (err != 0) error("error in toMixedBase");
            value[0] = hash_uint(cdf_format, var_type[i], var_rank[i], index,
                               NCT_UINT);
            err = nc_put_var1_uint(ncid, i, index, value);
            if (canConvert) {
                if (inRange3(cdf_format, (double)value[0],var_type[i],NCT_UINT)) {
                    IF (err != NC_NOERR)
                        error("expecting NC_NOERR but got %s",nc_err_code_name(err));
                    ELSE_NOK
                }
                
                    else {

                        IF (err != NC_ERANGE)
                            error("expecting NC_ERANGE but got %s",nc_err_code_name(err));
                        ELSE_NOK
                    }


            } else {
                IF (err != NC_ECHAR)
                    error("expecting NC_ECHAR but got %s",nc_err_code_name(err));
                ELSE_NOK
            }
        }
    }

    err =  nc_close(ncid);
    IF (err != NC_NOERR)
        error("close: %s",  nc_strerror(err));

    nok += check_vars_uint(scratch, numVars);

    err = nc_delete(scratch);
    IF (err != NC_NOERR)
        error("delete file %s failed", scratch);
    return nok;
}

int
test_nc_put_var1_longlong(void)
{
    int i, err, ncid, cdf_format, nok=0;
    int canConvert;      /* Both text or both numeric */
    size_t j, index[MAX_RANK];
    longlong value[1];

    err = file_create(scratch, NC_CLOBBER, &ncid);
    IF (err != NC_NOERR) {
        error("create: %s",  nc_strerror(err));
        return nok;
    }

    err =  nc_inq_format(ncid, &cdf_format);
    IF (err != NC_NOERR)
        error("inq_format: %s",  nc_strerror(err));

    def_dims(ncid);
    def_vars(ncid);

    err =  nc_enddef(ncid);
    IF (err != NC_NOERR)
        error("enddef: %s",  nc_strerror(err));

    /* check if can detect a bad file ID */
    err = nc_put_var1_longlong(BAD_ID, 0, NULL, NULL);
    IF (err != NC_EBADID)
        error("expecting NC_EBADID but got %s",nc_err_code_name(err));
    ELSE_NOK

    /* check if can detect a bad variable ID */
    err = nc_put_var1_longlong(ncid, BAD_VARID, NULL, NULL);
    IF (err != NC_ENOTVAR)
        error("expecting NC_ENOTVAR but got %s",nc_err_code_name(err));
    ELSE_NOK

    for (i = 0; i < numVars; i++) {
        assert(var_rank[i] <= MAX_RANK);
        assert(var_nels[i] <= MAX_NELS);

        value[0] = 5;  /* reset to a value within bounds */

        /* check if can detect a bad file ID */
        err = nc_put_var1_longlong(BAD_ID, i, NULL, value);
        IF (err != NC_EBADID)
            error("expecting NC_EBADID but got %s",nc_err_code_name(err));
        ELSE_NOK

        canConvert = (var_type[i] == NC_CHAR) == (NCT_LONGLONG == NCT_TEXT);


        /* test NC_EINVALCOORDS */
        for (j = 0; j < var_rank[i]; j++) index[j] = 0;

        for (j = 0; j < var_rank[i]; j++) {
            if (var_dimid[i][j] == RECDIM) continue; /* skip record dim */
            index[j] = var_shape[i][j];     /* out of boundary check */
            err = nc_put_var1_longlong(ncid, i, index, value);
            if (!canConvert) {
                IF (err != NC_ECHAR)
                    error("expecting NC_ECHAR but got %s",nc_err_code_name(err));
                ELSE_NOK
                index[j] = 0;
                continue;
            }
            IF (err != NC_EINVALCOORDS)
                error("expecting NC_EINVALCOORDS but got %s",nc_err_code_name(err));
            ELSE_NOK
            index[j] = 0;
        }

        for (j = 0; j < var_nels[i]; j++) {
            err = toMixedBase(j, var_rank[i], var_shape[i], index);
            IF (err != 0) error("error in toMixedBase");
            value[0] = hash_longlong(cdf_format, var_type[i], var_rank[i], index,
                               NCT_LONGLONG);
            err = nc_put_var1_longlong(ncid, i, index, value);
            if (canConvert) {
                if (inRange3(cdf_format, (double)value[0],var_type[i],NCT_LONGLONG)) {
                    IF (err != NC_NOERR)
                        error("expecting NC_NOERR but got %s",nc_err_code_name(err));
                    ELSE_NOK
                }
                
                    else {

                        IF (err != NC_ERANGE)
                            error("expecting NC_ERANGE but got %s",nc_err_code_name(err));
                        ELSE_NOK
                    }


            } else {
                IF (err != NC_ECHAR)
                    error("expecting NC_ECHAR but got %s",nc_err_code_name(err));
                ELSE_NOK
            }
        }
    }

    err =  nc_close(ncid);
    IF (err != NC_NOERR)
        error("close: %s",  nc_strerror(err));

    nok += check_vars_longlong(scratch, numVars);

    err = nc_delete(scratch);
    IF (err != NC_NOERR)
        error("delete file %s failed", scratch);
    return nok;
}

int
test_nc_put_var1_ulonglong(void)
{
    int i, err, ncid, cdf_format, nok=0;
    int canConvert;      /* Both text or both numeric */
    size_t j, index[MAX_RANK];
    ulonglong value[1];

    err = file_create(scratch, NC_CLOBBER, &ncid);
    IF (err != NC_NOERR) {
        error("create: %s",  nc_strerror(err));
        return nok;
    }

    err =  nc_inq_format(ncid, &cdf_format);
    IF (err != NC_NOERR)
        error("inq_format: %s",  nc_strerror(err));

    def_dims(ncid);
    def_vars(ncid);

    err =  nc_enddef(ncid);
    IF (err != NC_NOERR)
        error("enddef: %s",  nc_strerror(err));

    /* check if can detect a bad file ID */
    err = nc_put_var1_ulonglong(BAD_ID, 0, NULL, NULL);
    IF (err != NC_EBADID)
        error("expecting NC_EBADID but got %s",nc_err_code_name(err));
    ELSE_NOK

    /* check if can detect a bad variable ID */
    err = nc_put_var1_ulonglong(ncid, BAD_VARID, NULL, NULL);
    IF (err != NC_ENOTVAR)
        error("expecting NC_ENOTVAR but got %s",nc_err_code_name(err));
    ELSE_NOK

    for (i = 0; i < numVars; i++) {
        assert(var_rank[i] <= MAX_RANK);
        assert(var_nels[i] <= MAX_NELS);

        value[0] = 5;  /* reset to a value within bounds */

        /* check if can detect a bad file ID */
        err = nc_put_var1_ulonglong(BAD_ID, i, NULL, value);
        IF (err != NC_EBADID)
            error("expecting NC_EBADID but got %s",nc_err_code_name(err));
        ELSE_NOK

        canConvert = (var_type[i] == NC_CHAR) == (NCT_ULONGLONG == NCT_TEXT);


        /* test NC_EINVALCOORDS */
        for (j = 0; j < var_rank[i]; j++) index[j] = 0;

        for (j = 0; j < var_rank[i]; j++) {
            if (var_dimid[i][j] == RECDIM) continue; /* skip record dim */
            index[j] = var_shape[i][j];     /* out of boundary check */
            err = nc_put_var1_ulonglong(ncid, i, index, value);
            if (!canConvert) {
                IF (err != NC_ECHAR)
                    error("expecting NC_ECHAR but got %s",nc_err_code_name(err));
                ELSE_NOK
                index[j] = 0;
                continue;
            }
            IF (err != NC_EINVALCOORDS)
                error("expecting NC_EINVALCOORDS but got %s",nc_err_code_name(err));
            ELSE_NOK
            index[j] = 0;
        }

        for (j = 0; j < var_nels[i]; j++) {
            err = toMixedBase(j, var_rank[i], var_shape[i], index);
            IF (err != 0) error("error in toMixedBase");
            value[0] = hash_ulonglong(cdf_format, var_type[i], var_rank[i], index,
                               NCT_ULONGLONG);
            err = nc_put_var1_ulonglong(ncid, i, index, value);
            if (canConvert) {
                if (inRange3(cdf_format, (double)value[0],var_type[i],NCT_ULONGLONG)) {
                    IF (err != NC_NOERR)
                        error("expecting NC_NOERR but got %s",nc_err_code_name(err));
                    ELSE_NOK
                }
                
                    else {

                        IF (err != NC_ERANGE)
                            error("expecting NC_ERANGE but got %s",nc_err_code_name(err));
                        ELSE_NOK
                    }


            } else {
                IF (err != NC_ECHAR)
                    error("expecting NC_ECHAR but got %s",nc_err_code_name(err));
                ELSE_NOK
            }
        }
    }

    err =  nc_close(ncid);
    IF (err != NC_NOERR)
        error("close: %s",  nc_strerror(err));

    nok += check_vars_ulonglong(scratch, numVars);

    err = nc_delete(scratch);
    IF (err != NC_NOERR)
        error("delete file %s failed", scratch);
    return nok;
}




int
test_nc_put_var_text(void)
{
    int i, err, ncid, varid, cdf_format, nok=0;
    int canConvert;        /* Both text or both numeric */
    int allInExtRange;     /* all values within external range? */
    size_t j, index[MAX_RANK];
    text value[MAX_NELS];

    err = file_create(scratch, NC_CLOBBER, &ncid);
    IF (err != NC_NOERR) {
        error("create: %s",  nc_strerror(err));
        return nok;
    }

    err =  nc_inq_format(ncid, &cdf_format);
    IF (err != NC_NOERR)
        error("inq_format: %s",  nc_strerror(err));

    def_dims(ncid);
    def_vars(ncid);

    err =  nc_enddef(ncid);
    IF (err != NC_NOERR)
        error("enddef: %s",  nc_strerror(err));

    /* check if can detect a bad file ID */
    err = nc_put_var_text(BAD_ID, 0, NULL);
    IF (err != NC_EBADID)
        error("expecting NC_EBADID but got %s",nc_err_code_name(err));
    ELSE_NOK

    /* check if can detect a bad variable ID */
    err = nc_put_var_text(ncid, BAD_VARID, NULL);
    IF (err != NC_ENOTVAR)
        error("expecting NC_ENOTVAR but got %s",nc_err_code_name(err));
    ELSE_NOK

    for (i = 0; i < numVars; i++) {
        assert(var_rank[i] <= MAX_RANK);
        assert(var_nels[i] <= MAX_NELS);

        if (var_dimid[i][0] == RECDIM) continue; /* fixed-size variables only */

        value[0] = 5;  /* reset to a value within bounds */

        /* check if can detect a bad file ID */
        err = nc_put_var_text(BAD_ID, i, value);
        IF (err != NC_EBADID)
            error("expecting NC_EBADID but got %s",nc_err_code_name(err));
        ELSE_NOK

        canConvert = (var_type[i] == NC_CHAR) ;

        for (allInExtRange = 1, j = 0; j < var_nels[i]; j++) {
            err = toMixedBase(j, var_rank[i], var_shape[i], index);
            IF (err != 0) error("error in toMixedBase");
            value[j]= hash_text(cdf_format,var_type[i], var_rank[i], index,
                              NCT_TEXT);
            if (var_type[i] != NC_CHAR)
                allInExtRange &= inRange3(cdf_format, (double)value[j],
                                          var_type[i], NCT_TEXT);
        }
        err = nc_put_var_text(ncid, i, value);
        if (canConvert) {
            if (allInExtRange) {
                IF (err != NC_NOERR)
                    error("expecting NC_NOERR but got %s",nc_err_code_name(err));
                ELSE_NOK
            }
            
                    else {

                        IF (err != NC_ERANGE)
                            error("expecting NC_ERANGE but got %s",nc_err_code_name(err));
                        ELSE_NOK
                    }


        } else { /* should flag wrong type even if nothing to write */
            IF (err != NC_ECHAR)
                error("expecting NC_ECHAR but got %s",nc_err_code_name(err));
            ELSE_NOK
        }
    }

    /* Preceding has written nothing for record variables, now try */
    /* again with more than 0 records */

    /* Write record number NRECS to force writing of preceding records */
    /* Assumes variable cr is char vector with UNLIMITED dimension */
    err =  nc_inq_varid(ncid, "cr", &varid);
    IF (err != NC_NOERR)
        error("inq_varid: %s",  nc_strerror(err));
    index[0] = NRECS-1;
    err = nc_put_var1_text(ncid, varid, index, "x");
    IF (err != NC_NOERR)
        error("put_var1_text: %s",  nc_strerror(err));

    for (i = 0; i < numVars; i++) {
        if (var_dimid[i][0] != RECDIM) continue; /* only record variables here */

        canConvert = (var_type[i] == NC_CHAR) ;

        for (allInExtRange = 1, j = 0; j < var_nels[i]; j++) {
            err = toMixedBase(j, var_rank[i], var_shape[i], index);
            IF (err != 0) error("error in toMixedBase");
            value[j]= hash_text(cdf_format,var_type[i], var_rank[i], index,
                              NCT_TEXT);
            if (var_type[i] != NC_CHAR)
                allInExtRange &= inRange3(cdf_format, (double)value[j],
                                          var_type[i], NCT_TEXT);
        }
        err = nc_put_var_text(ncid, i, value);
        if (canConvert) {
            if (allInExtRange) {
                IF (err != NC_NOERR)
                    error("expecting NC_NOERR but got %s",nc_err_code_name(err));
                ELSE_NOK
            } else {
                IF (err != NC_ERANGE)
                    error("expecting NC_ERANGE but got %s",nc_err_code_name(err));
                ELSE_NOK
            }
        } else {
            IF (err != NC_ECHAR)
                error("expecting NC_ECHAR but got %s",nc_err_code_name(err));
            ELSE_NOK
        }
    }

    err =  nc_close(ncid);
    IF (err != NC_NOERR)
        error("close: %s",  nc_strerror(err));

    nok += check_vars_text(scratch, numVars);

    err = nc_delete(scratch);
    IF (err != NC_NOERR)
        error("delete file %s failed", scratch);
    return nok;
}

int
test_nc_put_var_uchar(void)
{
    int i, err, ncid, varid, cdf_format, nok=0;
    int canConvert;        /* Both text or both numeric */
    int allInExtRange;     /* all values within external range? */
    size_t j, index[MAX_RANK];
    uchar value[MAX_NELS];

    err = file_create(scratch, NC_CLOBBER, &ncid);
    IF (err != NC_NOERR) {
        error("create: %s",  nc_strerror(err));
        return nok;
    }

    err =  nc_inq_format(ncid, &cdf_format);
    IF (err != NC_NOERR)
        error("inq_format: %s",  nc_strerror(err));

    def_dims(ncid);
    def_vars(ncid);

    err =  nc_enddef(ncid);
    IF (err != NC_NOERR)
        error("enddef: %s",  nc_strerror(err));

    /* check if can detect a bad file ID */
    err = nc_put_var_uchar(BAD_ID, 0, NULL);
    IF (err != NC_EBADID)
        error("expecting NC_EBADID but got %s",nc_err_code_name(err));
    ELSE_NOK

    /* check if can detect a bad variable ID */
    err = nc_put_var_uchar(ncid, BAD_VARID, NULL);
    IF (err != NC_ENOTVAR)
        error("expecting NC_ENOTVAR but got %s",nc_err_code_name(err));
    ELSE_NOK

    for (i = 0; i < numVars; i++) {
        assert(var_rank[i] <= MAX_RANK);
        assert(var_nels[i] <= MAX_NELS);

        if (var_dimid[i][0] == RECDIM) continue; /* fixed-size variables only */

        value[0] = 5;  /* reset to a value within bounds */

        /* check if can detect a bad file ID */
        err = nc_put_var_uchar(BAD_ID, i, value);
        IF (err != NC_EBADID)
            error("expecting NC_EBADID but got %s",nc_err_code_name(err));
        ELSE_NOK

        canConvert = (var_type[i] == NC_CHAR) == (NCT_UCHAR == NCT_TEXT);

        for (allInExtRange = 1, j = 0; j < var_nels[i]; j++) {
            err = toMixedBase(j, var_rank[i], var_shape[i], index);
            IF (err != 0) error("error in toMixedBase");
            value[j]= hash_uchar(cdf_format,var_type[i], var_rank[i], index,
                              NCT_UCHAR);
            
                allInExtRange &= inRange3(cdf_format, (double)value[j],
                                          var_type[i], NCT_UCHAR);
        }
        err = nc_put_var_uchar(ncid, i, value);
        if (canConvert) {
            if (allInExtRange) {
                IF (err != NC_NOERR)
                    error("expecting NC_NOERR but got %s",nc_err_code_name(err));
                ELSE_NOK
            }
            
#if !defined(USE_PNETCDF) || (PNETCDF_VERSION_MAJOR==1 && PNETCDF_VERSION_MINOR>=8)
                    else {

                        IF (err != NC_ERANGE)
                            error("expecting NC_ERANGE but got %s",nc_err_code_name(err));
                        ELSE_NOK
                    }
#endif

        } else { /* should flag wrong type even if nothing to write */
            IF (err != NC_ECHAR)
                error("expecting NC_ECHAR but got %s",nc_err_code_name(err));
            ELSE_NOK
        }
    }

    /* Preceding has written nothing for record variables, now try */
    /* again with more than 0 records */

    /* Write record number NRECS to force writing of preceding records */
    /* Assumes variable cr is char vector with UNLIMITED dimension */
    err =  nc_inq_varid(ncid, "cr", &varid);
    IF (err != NC_NOERR)
        error("inq_varid: %s",  nc_strerror(err));
    index[0] = NRECS-1;
    err = nc_put_var1_text(ncid, varid, index, "x");
    IF (err != NC_NOERR)
        error("put_var1_text: %s",  nc_strerror(err));

    for (i = 0; i < numVars; i++) {
        if (var_dimid[i][0] != RECDIM) continue; /* only record variables here */

        canConvert = (var_type[i] == NC_CHAR) == (NCT_UCHAR == NCT_TEXT);

        for (allInExtRange = 1, j = 0; j < var_nels[i]; j++) {
            err = toMixedBase(j, var_rank[i], var_shape[i], index);
            IF (err != 0) error("error in toMixedBase");
            value[j]= hash_uchar(cdf_format,var_type[i], var_rank[i], index,
                              NCT_UCHAR);
            
                allInExtRange &= inRange3(cdf_format, (double)value[j],
                                          var_type[i], NCT_UCHAR);
        }
        err = nc_put_var_uchar(ncid, i, value);
        if (canConvert) {
            if (allInExtRange) {
                IF (err != NC_NOERR)
                    error("expecting NC_NOERR but got %s",nc_err_code_name(err));
                ELSE_NOK
            } else {
                IF (err != NC_ERANGE)
                    error("expecting NC_ERANGE but got %s",nc_err_code_name(err));
                ELSE_NOK
            }
        } else {
            IF (err != NC_ECHAR)
                error("expecting NC_ECHAR but got %s",nc_err_code_name(err));
            ELSE_NOK
        }
    }

    err =  nc_close(ncid);
    IF (err != NC_NOERR)
        error("close: %s",  nc_strerror(err));

    nok += check_vars_uchar(scratch, numVars);

    err = nc_delete(scratch);
    IF (err != NC_NOERR)
        error("delete file %s failed", scratch);
    return nok;
}

int
test_nc_put_var_schar(void)
{
    int i, err, ncid, varid, cdf_format, nok=0;
    int canConvert;        /* Both text or both numeric */
    int allInExtRange;     /* all values within external range? */
    size_t j, index[MAX_RANK];
    schar value[MAX_NELS];

    err = file_create(scratch, NC_CLOBBER, &ncid);
    IF (err != NC_NOERR) {
        error("create: %s",  nc_strerror(err));
        return nok;
    }

    err =  nc_inq_format(ncid, &cdf_format);
    IF (err != NC_NOERR)
        error("inq_format: %s",  nc_strerror(err));

    def_dims(ncid);
    def_vars(ncid);

    err =  nc_enddef(ncid);
    IF (err != NC_NOERR)
        error("enddef: %s",  nc_strerror(err));

    /* check if can detect a bad file ID */
    err = nc_put_var_schar(BAD_ID, 0, NULL);
    IF (err != NC_EBADID)
        error("expecting NC_EBADID but got %s",nc_err_code_name(err));
    ELSE_NOK

    /* check if can detect a bad variable ID */
    err = nc_put_var_schar(ncid, BAD_VARID, NULL);
    IF (err != NC_ENOTVAR)
        error("expecting NC_ENOTVAR but got %s",nc_err_code_name(err));
    ELSE_NOK

    for (i = 0; i < numVars; i++) {
        assert(var_rank[i] <= MAX_RANK);
        assert(var_nels[i] <= MAX_NELS);

        if (var_dimid[i][0] == RECDIM) continue; /* fixed-size variables only */

        value[0] = 5;  /* reset to a value within bounds */

        /* check if can detect a bad file ID */
        err = nc_put_var_schar(BAD_ID, i, value);
        IF (err != NC_EBADID)
            error("expecting NC_EBADID but got %s",nc_err_code_name(err));
        ELSE_NOK

        canConvert = (var_type[i] == NC_CHAR) == (NCT_SCHAR == NCT_TEXT);

        for (allInExtRange = 1, j = 0; j < var_nels[i]; j++) {
            err = toMixedBase(j, var_rank[i], var_shape[i], index);
            IF (err != 0) error("error in toMixedBase");
            value[j]= hash_schar(cdf_format,var_type[i], var_rank[i], index,
                              NCT_SCHAR);
            
                allInExtRange &= inRange3(cdf_format, (double)value[j],
                                          var_type[i], NCT_SCHAR);
        }
        err = nc_put_var_schar(ncid, i, value);
        if (canConvert) {
            if (allInExtRange) {
                IF (err != NC_NOERR)
                    error("expecting NC_NOERR but got %s",nc_err_code_name(err));
                ELSE_NOK
            }
            
#if defined(USE_PNETCDF) && PNETCDF_VERSION_MAJOR==1 && PNETCDF_VERSION_MINOR<7
                    else if (cdf_format < NC_FORMAT_CDF5) {
#else
                    else {
#endif
                        IF (err != NC_ERANGE)
                            error("expecting NC_ERANGE but got %s",nc_err_code_name(err));
                        ELSE_NOK
                    }


        } else { /* should flag wrong type even if nothing to write */
            IF (err != NC_ECHAR)
                error("expecting NC_ECHAR but got %s",nc_err_code_name(err));
            ELSE_NOK
        }
    }

    /* Preceding has written nothing for record variables, now try */
    /* again with more than 0 records */

    /* Write record number NRECS to force writing of preceding records */
    /* Assumes variable cr is char vector with UNLIMITED dimension */
    err =  nc_inq_varid(ncid, "cr", &varid);
    IF (err != NC_NOERR)
        error("inq_varid: %s",  nc_strerror(err));
    index[0] = NRECS-1;
    err = nc_put_var1_text(ncid, varid, index, "x");
    IF (err != NC_NOERR)
        error("put_var1_text: %s",  nc_strerror(err));

    for (i = 0; i < numVars; i++) {
        if (var_dimid[i][0] != RECDIM) continue; /* only record variables here */

        canConvert = (var_type[i] == NC_CHAR) == (NCT_SCHAR == NCT_TEXT);

        for (allInExtRange = 1, j = 0; j < var_nels[i]; j++) {
            err = toMixedBase(j, var_rank[i], var_shape[i], index);
            IF (err != 0) error("error in toMixedBase");
            value[j]= hash_schar(cdf_format,var_type[i], var_rank[i], index,
                              NCT_SCHAR);
            
                allInExtRange &= inRange3(cdf_format, (double)value[j],
                                          var_type[i], NCT_SCHAR);
        }
        err = nc_put_var_schar(ncid, i, value);
        if (canConvert) {
            if (allInExtRange) {
                IF (err != NC_NOERR)
                    error("expecting NC_NOERR but got %s",nc_err_code_name(err));
                ELSE_NOK
            } else {
                IF (err != NC_ERANGE)
                    error("expecting NC_ERANGE but got %s",nc_err_code_name(err));
                ELSE_NOK
            }
        } else {
            IF (err != NC_ECHAR)
                error("expecting NC_ECHAR but got %s",nc_err_code_name(err));
            ELSE_NOK
        }
    }

    err =  nc_close(ncid);
    IF (err != NC_NOERR)
        error("close: %s",  nc_strerror(err));

    nok += check_vars_schar(scratch, numVars);

    err = nc_delete(scratch);
    IF (err != NC_NOERR)
        error("delete file %s failed", scratch);
    return nok;
}

int
test_nc_put_var_short(void)
{
    int i, err, ncid, varid, cdf_format, nok=0;
    int canConvert;        /* Both text or both numeric */
    int allInExtRange;     /* all values within external range? */
    size_t j, index[MAX_RANK];
    short value[MAX_NELS];

    err = file_create(scratch, NC_CLOBBER, &ncid);
    IF (err != NC_NOERR) {
        error("create: %s",  nc_strerror(err));
        return nok;
    }

    err =  nc_inq_format(ncid, &cdf_format);
    IF (err != NC_NOERR)
        error("inq_format: %s",  nc_strerror(err));

    def_dims(ncid);
    def_vars(ncid);

    err =  nc_enddef(ncid);
    IF (err != NC_NOERR)
        error("enddef: %s",  nc_strerror(err));

    /* check if can detect a bad file ID */
    err = nc_put_var_short(BAD_ID, 0, NULL);
    IF (err != NC_EBADID)
        error("expecting NC_EBADID but got %s",nc_err_code_name(err));
    ELSE_NOK

    /* check if can detect a bad variable ID */
    err = nc_put_var_short(ncid, BAD_VARID, NULL);
    IF (err != NC_ENOTVAR)
        error("expecting NC_ENOTVAR but got %s",nc_err_code_name(err));
    ELSE_NOK

    for (i = 0; i < numVars; i++) {
        assert(var_rank[i] <= MAX_RANK);
        assert(var_nels[i] <= MAX_NELS);

        if (var_dimid[i][0] == RECDIM) continue; /* fixed-size variables only */

        value[0] = 5;  /* reset to a value within bounds */

        /* check if can detect a bad file ID */
        err = nc_put_var_short(BAD_ID, i, value);
        IF (err != NC_EBADID)
            error("expecting NC_EBADID but got %s",nc_err_code_name(err));
        ELSE_NOK

        canConvert = (var_type[i] == NC_CHAR) == (NCT_SHORT == NCT_TEXT);

        for (allInExtRange = 1, j = 0; j < var_nels[i]; j++) {
            err = toMixedBase(j, var_rank[i], var_shape[i], index);
            IF (err != 0) error("error in toMixedBase");
            value[j]= hash_short(cdf_format,var_type[i], var_rank[i], index,
                              NCT_SHORT);
            
                allInExtRange &= inRange3(cdf_format, (double)value[j],
                                          var_type[i], NCT_SHORT);
        }
        err = nc_put_var_short(ncid, i, value);
        if (canConvert) {
            if (allInExtRange) {
                IF (err != NC_NOERR)
                    error("expecting NC_NOERR but got %s",nc_err_code_name(err));
                ELSE_NOK
            }
            
                    else {

                        IF (err != NC_ERANGE)
                            error("expecting NC_ERANGE but got %s",nc_err_code_name(err));
                        ELSE_NOK
                    }


        } else { /* should flag wrong type even if nothing to write */
            IF (err != NC_ECHAR)
                error("expecting NC_ECHAR but got %s",nc_err_code_name(err));
            ELSE_NOK
        }
    }

    /* Preceding has written nothing for record variables, now try */
    /* again with more than 0 records */

    /* Write record number NRECS to force writing of preceding records */
    /* Assumes variable cr is char vector with UNLIMITED dimension */
    err =  nc_inq_varid(ncid, "cr", &varid);
    IF (err != NC_NOERR)
        error("inq_varid: %s",  nc_strerror(err));
    index[0] = NRECS-1;
    err = nc_put_var1_text(ncid, varid, index, "x");
    IF (err != NC_NOERR)
        error("put_var1_text: %s",  nc_strerror(err));

    for (i = 0; i < numVars; i++) {
        if (var_dimid[i][0] != RECDIM) continue; /* only record variables here */

        canConvert = (var_type[i] == NC_CHAR) == (NCT_SHORT == NCT_TEXT);

        for (allInExtRange = 1, j = 0; j < var_nels[i]; j++) {
            err = toMixedBase(j, var_rank[i], var_shape[i], index);
            IF (err != 0) error("error in toMixedBase");
            value[j]= hash_short(cdf_format,var_type[i], var_rank[i], index,
                              NCT_SHORT);
            
                allInExtRange &= inRange3(cdf_format, (double)value[j],
                                          var_type[i], NCT_SHORT);
        }
        err = nc_put_var_short(ncid, i, value);
        if (canConvert) {
            if (allInExtRange) {
                IF (err != NC_NOERR)
                    error("expecting NC_NOERR but got %s",nc_err_code_name(err));
                ELSE_NOK
            } else {
                IF (err != NC_ERANGE)
                    error("expecting NC_ERANGE but got %s",nc_err_code_name(err));
                ELSE_NOK
            }
        } else {
            IF (err != NC_ECHAR)
                error("expecting NC_ECHAR but got %s",nc_err_code_name(err));
            ELSE_NOK
        }
    }

    err =  nc_close(ncid);
    IF (err != NC_NOERR)
        error("close: %s",  nc_strerror(err));

    nok += check_vars_short(scratch, numVars);

    err = nc_delete(scratch);
    IF (err != NC_NOERR)
        error("delete file %s failed", scratch);
    return nok;
}

int
test_nc_put_var_int(void)
{
    int i, err, ncid, varid, cdf_format, nok=0;
    int canConvert;        /* Both text or both numeric */
    int allInExtRange;     /* all values within external range? */
    size_t j, index[MAX_RANK];
    int value[MAX_NELS];

    err = file_create(scratch, NC_CLOBBER, &ncid);
    IF (err != NC_NOERR) {
        error("create: %s",  nc_strerror(err));
        return nok;
    }

    err =  nc_inq_format(ncid, &cdf_format);
    IF (err != NC_NOERR)
        error("inq_format: %s",  nc_strerror(err));

    def_dims(ncid);
    def_vars(ncid);

    err =  nc_enddef(ncid);
    IF (err != NC_NOERR)
        error("enddef: %s",  nc_strerror(err));

    /* check if can detect a bad file ID */
    err = nc_put_var_int(BAD_ID, 0, NULL);
    IF (err != NC_EBADID)
        error("expecting NC_EBADID but got %s",nc_err_code_name(err));
    ELSE_NOK

    /* check if can detect a bad variable ID */
    err = nc_put_var_int(ncid, BAD_VARID, NULL);
    IF (err != NC_ENOTVAR)
        error("expecting NC_ENOTVAR but got %s",nc_err_code_name(err));
    ELSE_NOK

    for (i = 0; i < numVars; i++) {
        assert(var_rank[i] <= MAX_RANK);
        assert(var_nels[i] <= MAX_NELS);

        if (var_dimid[i][0] == RECDIM) continue; /* fixed-size variables only */

        value[0] = 5;  /* reset to a value within bounds */

        /* check if can detect a bad file ID */
        err = nc_put_var_int(BAD_ID, i, value);
        IF (err != NC_EBADID)
            error("expecting NC_EBADID but got %s",nc_err_code_name(err));
        ELSE_NOK

        canConvert = (var_type[i] == NC_CHAR) == (NCT_INT == NCT_TEXT);

        for (allInExtRange = 1, j = 0; j < var_nels[i]; j++) {
            err = toMixedBase(j, var_rank[i], var_shape[i], index);
            IF (err != 0) error("error in toMixedBase");
            value[j]= hash_int(cdf_format,var_type[i], var_rank[i], index,
                              NCT_INT);
            
                allInExtRange &= inRange3(cdf_format, (double)value[j],
                                          var_type[i], NCT_INT);
        }
        err = nc_put_var_int(ncid, i, value);
        if (canConvert) {
            if (allInExtRange) {
                IF (err != NC_NOERR)
                    error("expecting NC_NOERR but got %s",nc_err_code_name(err));
                ELSE_NOK
            }
            
                    else {

                        IF (err != NC_ERANGE)
                            error("expecting NC_ERANGE but got %s",nc_err_code_name(err));
                        ELSE_NOK
                    }


        } else { /* should flag wrong type even if nothing to write */
            IF (err != NC_ECHAR)
                error("expecting NC_ECHAR but got %s",nc_err_code_name(err));
            ELSE_NOK
        }
    }

    /* Preceding has written nothing for record variables, now try */
    /* again with more than 0 records */

    /* Write record number NRECS to force writing of preceding records */
    /* Assumes variable cr is char vector with UNLIMITED dimension */
    err =  nc_inq_varid(ncid, "cr", &varid);
    IF (err != NC_NOERR)
        error("inq_varid: %s",  nc_strerror(err));
    index[0] = NRECS-1;
    err = nc_put_var1_text(ncid, varid, index, "x");
    IF (err != NC_NOERR)
        error("put_var1_text: %s",  nc_strerror(err));

    for (i = 0; i < numVars; i++) {
        if (var_dimid[i][0] != RECDIM) continue; /* only record variables here */

        canConvert = (var_type[i] == NC_CHAR) == (NCT_INT == NCT_TEXT);

        for (allInExtRange = 1, j = 0; j < var_nels[i]; j++) {
            err = toMixedBase(j, var_rank[i], var_shape[i], index);
            IF (err != 0) error("error in toMixedBase");
            value[j]= hash_int(cdf_format,var_type[i], var_rank[i], index,
                              NCT_INT);
            
                allInExtRange &= inRange3(cdf_format, (double)value[j],
                                          var_type[i], NCT_INT);
        }
        err = nc_put_var_int(ncid, i, value);
        if (canConvert) {
            if (allInExtRange) {
                IF (err != NC_NOERR)
                    error("expecting NC_NOERR but got %s",nc_err_code_name(err));
                ELSE_NOK
            } else {
                IF (err != NC_ERANGE)
                    error("expecting NC_ERANGE but got %s",nc_err_code_name(err));
                ELSE_NOK
            }
        } else {
            IF (err != NC_ECHAR)
                error("expecting NC_ECHAR but got %s",nc_err_code_name(err));
            ELSE_NOK
        }
    }

    err =  nc_close(ncid);
    IF (err != NC_NOERR)
        error("close: %s",  nc_strerror(err));

    nok += check_vars_int(scratch, numVars);

    err = nc_delete(scratch);
    IF (err != NC_NOERR)
        error("delete file %s failed", scratch);
    return nok;
}

int
test_nc_put_var_long(void)
{
    int i, err, ncid, varid, cdf_format, nok=0;
    int canConvert;        /* Both text or both numeric */
    int allInExtRange;     /* all values within external range? */
    size_t j, index[MAX_RANK];
    long value[MAX_NELS];

    err = file_create(scratch, NC_CLOBBER, &ncid);
    IF (err != NC_NOERR) {
        error("create: %s",  nc_strerror(err));
        return nok;
    }

    err =  nc_inq_format(ncid, &cdf_format);
    IF (err != NC_NOERR)
        error("inq_format: %s",  nc_strerror(err));

    def_dims(ncid);
    def_vars(ncid);

    err =  nc_enddef(ncid);
    IF (err != NC_NOERR)
        error("enddef: %s",  nc_strerror(err));

    /* check if can detect a bad file ID */
    err = nc_put_var_long(BAD_ID, 0, NULL);
    IF (err != NC_EBADID)
        error("expecting NC_EBADID but got %s",nc_err_code_name(err));
    ELSE_NOK

    /* check if can detect a bad variable ID */
    err = nc_put_var_long(ncid, BAD_VARID, NULL);
    IF (err != NC_ENOTVAR)
        error("expecting NC_ENOTVAR but got %s",nc_err_code_name(err));
    ELSE_NOK

    for (i = 0; i < numVars; i++) {
        assert(var_rank[i] <= MAX_RANK);
        assert(var_nels[i] <= MAX_NELS);

        if (var_dimid[i][0] == RECDIM) continue; /* fixed-size variables only */

        value[0] = 5;  /* reset to a value within bounds */

        /* check if can detect a bad file ID */
        err = nc_put_var_long(BAD_ID, i, value);
        IF (err != NC_EBADID)
            error("expecting NC_EBADID but got %s",nc_err_code_name(err));
        ELSE_NOK

        canConvert = (var_type[i] == NC_CHAR) == (NCT_LONG == NCT_TEXT);

        for (allInExtRange = 1, j = 0; j < var_nels[i]; j++) {
            err = toMixedBase(j, var_rank[i], var_shape[i], index);
            IF (err != 0) error("error in toMixedBase");
            value[j]= hash_long(cdf_format,var_type[i], var_rank[i], index,
                              NCT_LONG);
            
                allInExtRange &= inRange3(cdf_format, (double)value[j],
                                          var_type[i], NCT_LONG);
        }
        err = nc_put_var_long(ncid, i, value);
        if (canConvert) {
            if (allInExtRange) {
                IF (err != NC_NOERR)
                    error("expecting NC_NOERR but got %s",nc_err_code_name(err));
                ELSE_NOK
            }
            
                    else {

                        IF (err != NC_ERANGE)
                            error("expecting NC_ERANGE but got %s",nc_err_code_name(err));
                        ELSE_NOK
                    }


        } else { /* should flag wrong type even if nothing to write */
            IF (err != NC_ECHAR)
                error("expecting NC_ECHAR but got %s",nc_err_code_name(err));
            ELSE_NOK
        }
    }

    /* Preceding has written nothing for record variables, now try */
    /* again with more than 0 records */

    /* Write record number NRECS to force writing of preceding records */
    /* Assumes variable cr is char vector with UNLIMITED dimension */
    err =  nc_inq_varid(ncid, "cr", &varid);
    IF (err != NC_NOERR)
        error("inq_varid: %s",  nc_strerror(err));
    index[0] = NRECS-1;
    err = nc_put_var1_text(ncid, varid, index, "x");
    IF (err != NC_NOERR)
        error("put_var1_text: %s",  nc_strerror(err));

    for (i = 0; i < numVars; i++) {
        if (var_dimid[i][0] != RECDIM) continue; /* only record variables here */

        canConvert = (var_type[i] == NC_CHAR) == (NCT_LONG == NCT_TEXT);

        for (allInExtRange = 1, j = 0; j < var_nels[i]; j++) {
            err = toMixedBase(j, var_rank[i], var_shape[i], index);
            IF (err != 0) error("error in toMixedBase");
            value[j]= hash_long(cdf_format,var_type[i], var_rank[i], index,
                              NCT_LONG);
            
                allInExtRange &= inRange3(cdf_format, (double)value[j],
                                          var_type[i], NCT_LONG);
        }
        err = nc_put_var_long(ncid, i, value);
        if (canConvert) {
            if (allInExtRange) {
                IF (err != NC_NOERR)
                    error("expecting NC_NOERR but got %s",nc_err_code_name(err));
                ELSE_NOK
            } else {
                IF (err != NC_ERANGE)
                    error("expecting NC_ERANGE but got %s",nc_err_code_name(err));
                ELSE_NOK
            }
        } else {
            IF (err != NC_ECHAR)
                error("expecting NC_ECHAR but got %s",nc_err_code_name(err));
            ELSE_NOK
        }
    }

    err =  nc_close(ncid);
    IF (err != NC_NOERR)
        error("close: %s",  nc_strerror(err));

    nok += check_vars_long(scratch, numVars);

    err = nc_delete(scratch);
    IF (err != NC_NOERR)
        error("delete file %s failed", scratch);
    return nok;
}

int
test_nc_put_var_float(void)
{
    int i, err, ncid, varid, cdf_format, nok=0;
    int canConvert;        /* Both text or both numeric */
    int allInExtRange;     /* all values within external range? */
    size_t j, index[MAX_RANK];
    float value[MAX_NELS];

    err = file_create(scratch, NC_CLOBBER, &ncid);
    IF (err != NC_NOERR) {
        error("create: %s",  nc_strerror(err));
        return nok;
    }

    err =  nc_inq_format(ncid, &cdf_format);
    IF (err != NC_NOERR)
        error("inq_format: %s",  nc_strerror(err));

    def_dims(ncid);
    def_vars(ncid);

    err =  nc_enddef(ncid);
    IF (err != NC_NOERR)
        error("enddef: %s",  nc_strerror(err));

    /* check if can detect a bad file ID */
    err = nc_put_var_float(BAD_ID, 0, NULL);
    IF (err != NC_EBADID)
        error("expecting NC_EBADID but got %s",nc_err_code_name(err));
    ELSE_NOK

    /* check if can detect a bad variable ID */
    err = nc_put_var_float(ncid, BAD_VARID, NULL);
    IF (err != NC_ENOTVAR)
        error("expecting NC_ENOTVAR but got %s",nc_err_code_name(err));
    ELSE_NOK

    for (i = 0; i < numVars; i++) {
        assert(var_rank[i] <= MAX_RANK);
        assert(var_nels[i] <= MAX_NELS);

        if (var_dimid[i][0] == RECDIM) continue; /* fixed-size variables only */

        value[0] = 5;  /* reset to a value within bounds */

        /* check if can detect a bad file ID */
        err = nc_put_var_float(BAD_ID, i, value);
        IF (err != NC_EBADID)
            error("expecting NC_EBADID but got %s",nc_err_code_name(err));
        ELSE_NOK

        canConvert = (var_type[i] == NC_CHAR) == (NCT_FLOAT == NCT_TEXT);

        for (allInExtRange = 1, j = 0; j < var_nels[i]; j++) {
            err = toMixedBase(j, var_rank[i], var_shape[i], index);
            IF (err != 0) error("error in toMixedBase");
            value[j]= hash_float(cdf_format,var_type[i], var_rank[i], index,
                              NCT_FLOAT);
            
                allInExtRange &= inRange3(cdf_format, (double)value[j],
                                          var_type[i], NCT_FLOAT);
        }
        err = nc_put_var_float(ncid, i, value);
        if (canConvert) {
            if (allInExtRange) {
                IF (err != NC_NOERR)
                    error("expecting NC_NOERR but got %s",nc_err_code_name(err));
                ELSE_NOK
            }
            
                    else {

                        IF (err != NC_ERANGE)
                            error("expecting NC_ERANGE but got %s",nc_err_code_name(err));
                        ELSE_NOK
                    }


        } else { /* should flag wrong type even if nothing to write */
            IF (err != NC_ECHAR)
                error("expecting NC_ECHAR but got %s",nc_err_code_name(err));
            ELSE_NOK
        }
    }

    /* Preceding has written nothing for record variables, now try */
    /* again with more than 0 records */

    /* Write record number NRECS to force writing of preceding records */
    /* Assumes variable cr is char vector with UNLIMITED dimension */
    err =  nc_inq_varid(ncid, "cr", &varid);
    IF (err != NC_NOERR)
        error("inq_varid: %s",  nc_strerror(err));
    index[0] = NRECS-1;
    err = nc_put_var1_text(ncid, varid, index, "x");
    IF (err != NC_NOERR)
        error("put_var1_text: %s",  nc_strerror(err));

    for (i = 0; i < numVars; i++) {
        if (var_dimid[i][0] != RECDIM) continue; /* only record variables here */

        canConvert = (var_type[i] == NC_CHAR) == (NCT_FLOAT == NCT_TEXT);

        for (allInExtRange = 1, j = 0; j < var_nels[i]; j++) {
            err = toMixedBase(j, var_rank[i], var_shape[i], index);
            IF (err != 0) error("error in toMixedBase");
            value[j]= hash_float(cdf_format,var_type[i], var_rank[i], index,
                              NCT_FLOAT);
            
                allInExtRange &= inRange3(cdf_format, (double)value[j],
                                          var_type[i], NCT_FLOAT);
        }
        err = nc_put_var_float(ncid, i, value);
        if (canConvert) {
            if (allInExtRange) {
                IF (err != NC_NOERR)
                    error("expecting NC_NOERR but got %s",nc_err_code_name(err));
                ELSE_NOK
            } else {
                IF (err != NC_ERANGE)
                    error("expecting NC_ERANGE but got %s",nc_err_code_name(err));
                ELSE_NOK
            }
        } else {
            IF (err != NC_ECHAR)
                error("expecting NC_ECHAR but got %s",nc_err_code_name(err));
            ELSE_NOK
        }
    }

    err =  nc_close(ncid);
    IF (err != NC_NOERR)
        error("close: %s",  nc_strerror(err));

    nok += check_vars_float(scratch, numVars);

    err = nc_delete(scratch);
    IF (err != NC_NOERR)
        error("delete file %s failed", scratch);
    return nok;
}

int
test_nc_put_var_double(void)
{
    int i, err, ncid, varid, cdf_format, nok=0;
    int canConvert;        /* Both text or both numeric */
    int allInExtRange;     /* all values within external range? */
    size_t j, index[MAX_RANK];
    double value[MAX_NELS];

    err = file_create(scratch, NC_CLOBBER, &ncid);
    IF (err != NC_NOERR) {
        error("create: %s",  nc_strerror(err));
        return nok;
    }

    err =  nc_inq_format(ncid, &cdf_format);
    IF (err != NC_NOERR)
        error("inq_format: %s",  nc_strerror(err));

    def_dims(ncid);
    def_vars(ncid);

    err =  nc_enddef(ncid);
    IF (err != NC_NOERR)
        error("enddef: %s",  nc_strerror(err));

    /* check if can detect a bad file ID */
    err = nc_put_var_double(BAD_ID, 0, NULL);
    IF (err != NC_EBADID)
        error("expecting NC_EBADID but got %s",nc_err_code_name(err));
    ELSE_NOK

    /* check if can detect a bad variable ID */
    err = nc_put_var_double(ncid, BAD_VARID, NULL);
    IF (err != NC_ENOTVAR)
        error("expecting NC_ENOTVAR but got %s",nc_err_code_name(err));
    ELSE_NOK

    for (i = 0; i < numVars; i++) {
        assert(var_rank[i] <= MAX_RANK);
        assert(var_nels[i] <= MAX_NELS);

        if (var_dimid[i][0] == RECDIM) continue; /* fixed-size variables only */

        value[0] = 5;  /* reset to a value within bounds */

        /* check if can detect a bad file ID */
        err = nc_put_var_double(BAD_ID, i, value);
        IF (err != NC_EBADID)
            error("expecting NC_EBADID but got %s",nc_err_code_name(err));
        ELSE_NOK

        canConvert = (var_type[i] == NC_CHAR) == (NCT_DOUBLE == NCT_TEXT);

        for (allInExtRange = 1, j = 0; j < var_nels[i]; j++) {
            err = toMixedBase(j, var_rank[i], var_shape[i], index);
            IF (err != 0) error("error in toMixedBase");
            value[j]= hash_double(cdf_format,var_type[i], var_rank[i], index,
                              NCT_DOUBLE);
            
                allInExtRange &= inRange3(cdf_format, (double)value[j],
                                          var_type[i], NCT_DOUBLE);
        }
        err = nc_put_var_double(ncid, i, value);
        if (canConvert) {
            if (allInExtRange) {
                IF (err != NC_NOERR)
                    error("expecting NC_NOERR but got %s",nc_err_code_name(err));
                ELSE_NOK
            }
            
                    else {

                        IF (err != NC_ERANGE)
                            error("expecting NC_ERANGE but got %s",nc_err_code_name(err));
                        ELSE_NOK
                    }


        } else { /* should flag wrong type even if nothing to write */
            IF (err != NC_ECHAR)
                error("expecting NC_ECHAR but got %s",nc_err_code_name(err));
            ELSE_NOK
        }
    }

    /* Preceding has written nothing for record variables, now try */
    /* again with more than 0 records */

    /* Write record number NRECS to force writing of preceding records */
    /* Assumes variable cr is char vector with UNLIMITED dimension */
    err =  nc_inq_varid(ncid, "cr", &varid);
    IF (err != NC_NOERR)
        error("inq_varid: %s",  nc_strerror(err));
    index[0] = NRECS-1;
    err = nc_put_var1_text(ncid, varid, index, "x");
    IF (err != NC_NOERR)
        error("put_var1_text: %s",  nc_strerror(err));

    for (i = 0; i < numVars; i++) {
        if (var_dimid[i][0] != RECDIM) continue; /* only record variables here */

        canConvert = (var_type[i] == NC_CHAR) == (NCT_DOUBLE == NCT_TEXT);

        for (allInExtRange = 1, j = 0; j < var_nels[i]; j++) {
            err = toMixedBase(j, var_rank[i], var_shape[i], index);
            IF (err != 0) error("error in toMixedBase");
            value[j]= hash_double(cdf_format,var_type[i], var_rank[i], index,
                              NCT_DOUBLE);
            
                allInExtRange &= inRange3(cdf_format, (double)value[j],
                                          var_type[i], NCT_DOUBLE);
        }
        err = nc_put_var_double(ncid, i, value);
        if (canConvert) {
            if (allInExtRange) {
                IF (err != NC_NOERR)
                    error("expecting NC_NOERR but got %s",nc_err_code_name(err));
                ELSE_NOK
            } else {
                IF (err != NC_ERANGE)
                    error("expecting NC_ERANGE but got %s",nc_err_code_name(err));
                ELSE_NOK
            }
        } else {
            IF (err != NC_ECHAR)
                error("expecting NC_ECHAR but got %s",nc_err_code_name(err));
            ELSE_NOK
        }
    }

    err =  nc_close(ncid);
    IF (err != NC_NOERR)
        error("close: %s",  nc_strerror(err));

    nok += check_vars_double(scratch, numVars);

    err = nc_delete(scratch);
    IF (err != NC_NOERR)
        error("delete file %s failed", scratch);
    return nok;
}

int
test_nc_put_var_ushort(void)
{
    int i, err, ncid, varid, cdf_format, nok=0;
    int canConvert;        /* Both text or both numeric */
    int allInExtRange;     /* all values within external range? */
    size_t j, index[MAX_RANK];
    ushort value[MAX_NELS];

    err = file_create(scratch, NC_CLOBBER, &ncid);
    IF (err != NC_NOERR) {
        error("create: %s",  nc_strerror(err));
        return nok;
    }

    err =  nc_inq_format(ncid, &cdf_format);
    IF (err != NC_NOERR)
        error("inq_format: %s",  nc_strerror(err));

    def_dims(ncid);
    def_vars(ncid);

    err =  nc_enddef(ncid);
    IF (err != NC_NOERR)
        error("enddef: %s",  nc_strerror(err));

    /* check if can detect a bad file ID */
    err = nc_put_var_ushort(BAD_ID, 0, NULL);
    IF (err != NC_EBADID)
        error("expecting NC_EBADID but got %s",nc_err_code_name(err));
    ELSE_NOK

    /* check if can detect a bad variable ID */
    err = nc_put_var_ushort(ncid, BAD_VARID, NULL);
    IF (err != NC_ENOTVAR)
        error("expecting NC_ENOTVAR but got %s",nc_err_code_name(err));
    ELSE_NOK

    for (i = 0; i < numVars; i++) {
        assert(var_rank[i] <= MAX_RANK);
        assert(var_nels[i] <= MAX_NELS);

        if (var_dimid[i][0] == RECDIM) continue; /* fixed-size variables only */

        value[0] = 5;  /* reset to a value within bounds */

        /* check if can detect a bad file ID */
        err = nc_put_var_ushort(BAD_ID, i, value);
        IF (err != NC_EBADID)
            error("expecting NC_EBADID but got %s",nc_err_code_name(err));
        ELSE_NOK

        canConvert = (var_type[i] == NC_CHAR) == (NCT_USHORT == NCT_TEXT);

        for (allInExtRange = 1, j = 0; j < var_nels[i]; j++) {
            err = toMixedBase(j, var_rank[i], var_shape[i], index);
            IF (err != 0) error("error in toMixedBase");
            value[j]= hash_ushort(cdf_format,var_type[i], var_rank[i], index,
                              NCT_USHORT);
            
                allInExtRange &= inRange3(cdf_format, (double)value[j],
                                          var_type[i], NCT_USHORT);
        }
        err = nc_put_var_ushort(ncid, i, value);
        if (canConvert) {
            if (allInExtRange) {
                IF (err != NC_NOERR)
                    error("expecting NC_NOERR but got %s",nc_err_code_name(err));
                ELSE_NOK
            }
            
                    else {

                        IF (err != NC_ERANGE)
                            error("expecting NC_ERANGE but got %s",nc_err_code_name(err));
                        ELSE_NOK
                    }


        } else { /* should flag wrong type even if nothing to write */
            IF (err != NC_ECHAR)
                error("expecting NC_ECHAR but got %s",nc_err_code_name(err));
            ELSE_NOK
        }
    }

    /* Preceding has written nothing for record variables, now try */
    /* again with more than 0 records */

    /* Write record number NRECS to force writing of preceding records */
    /* Assumes variable cr is char vector with UNLIMITED dimension */
    err =  nc_inq_varid(ncid, "cr", &varid);
    IF (err != NC_NOERR)
        error("inq_varid: %s",  nc_strerror(err));
    index[0] = NRECS-1;
    err = nc_put_var1_text(ncid, varid, index, "x");
    IF (err != NC_NOERR)
        error("put_var1_text: %s",  nc_strerror(err));

    for (i = 0; i < numVars; i++) {
        if (var_dimid[i][0] != RECDIM) continue; /* only record variables here */

        canConvert = (var_type[i] == NC_CHAR) == (NCT_USHORT == NCT_TEXT);

        for (allInExtRange = 1, j = 0; j < var_nels[i]; j++) {
            err = toMixedBase(j, var_rank[i], var_shape[i], index);
            IF (err != 0) error("error in toMixedBase");
            value[j]= hash_ushort(cdf_format,var_type[i], var_rank[i], index,
                              NCT_USHORT);
            
                allInExtRange &= inRange3(cdf_format, (double)value[j],
                                          var_type[i], NCT_USHORT);
        }
        err = nc_put_var_ushort(ncid, i, value);
        if (canConvert) {
            if (allInExtRange) {
                IF (err != NC_NOERR)
                    error("expecting NC_NOERR but got %s",nc_err_code_name(err));
                ELSE_NOK
            } else {
                IF (err != NC_ERANGE)
                    error("expecting NC_ERANGE but got %s",nc_err_code_name(err));
                ELSE_NOK
            }
        } else {
            IF (err != NC_ECHAR)
                error("expecting NC_ECHAR but got %s",nc_err_code_name(err));
            ELSE_NOK
        }
    }

    err =  nc_close(ncid);
    IF (err != NC_NOERR)
        error("close: %s",  nc_strerror(err));

    nok += check_vars_ushort(scratch, numVars);

    err = nc_delete(scratch);
    IF (err != NC_NOERR)
        error("delete file %s failed", scratch);
    return nok;
}

int
test_nc_put_var_uint(void)
{
    int i, err, ncid, varid, cdf_format, nok=0;
    int canConvert;        /* Both text or both numeric */
    int allInExtRange;     /* all values within external range? */
    size_t j, index[MAX_RANK];
    uint value[MAX_NELS];

    err = file_create(scratch, NC_CLOBBER, &ncid);
    IF (err != NC_NOERR) {
        error("create: %s",  nc_strerror(err));
        return nok;
    }

    err =  nc_inq_format(ncid, &cdf_format);
    IF (err != NC_NOERR)
        error("inq_format: %s",  nc_strerror(err));

    def_dims(ncid);
    def_vars(ncid);

    err =  nc_enddef(ncid);
    IF (err != NC_NOERR)
        error("enddef: %s",  nc_strerror(err));

    /* check if can detect a bad file ID */
    err = nc_put_var_uint(BAD_ID, 0, NULL);
    IF (err != NC_EBADID)
        error("expecting NC_EBADID but got %s",nc_err_code_name(err));
    ELSE_NOK

    /* check if can detect a bad variable ID */
    err = nc_put_var_uint(ncid, BAD_VARID, NULL);
    IF (err != NC_ENOTVAR)
        error("expecting NC_ENOTVAR but got %s",nc_err_code_name(err));
    ELSE_NOK

    for (i = 0; i < numVars; i++) {
        assert(var_rank[i] <= MAX_RANK);
        assert(var_nels[i] <= MAX_NELS);

        if (var_dimid[i][0] == RECDIM) continue; /* fixed-size variables only */

        value[0] = 5;  /* reset to a value within bounds */

        /* check if can detect a bad file ID */
        err = nc_put_var_uint(BAD_ID, i, value);
        IF (err != NC_EBADID)
            error("expecting NC_EBADID but got %s",nc_err_code_name(err));
        ELSE_NOK

        canConvert = (var_type[i] == NC_CHAR) == (NCT_UINT == NCT_TEXT);

        for (allInExtRange = 1, j = 0; j < var_nels[i]; j++) {
            err = toMixedBase(j, var_rank[i], var_shape[i], index);
            IF (err != 0) error("error in toMixedBase");
            value[j]= hash_uint(cdf_format,var_type[i], var_rank[i], index,
                              NCT_UINT);
            
                allInExtRange &= inRange3(cdf_format, (double)value[j],
                                          var_type[i], NCT_UINT);
        }
        err = nc_put_var_uint(ncid, i, value);
        if (canConvert) {
            if (allInExtRange) {
                IF (err != NC_NOERR)
                    error("expecting NC_NOERR but got %s",nc_err_code_name(err));
                ELSE_NOK
            }
            
                    else {

                        IF (err != NC_ERANGE)
                            error("expecting NC_ERANGE but got %s",nc_err_code_name(err));
                        ELSE_NOK
                    }


        } else { /* should flag wrong type even if nothing to write */
            IF (err != NC_ECHAR)
                error("expecting NC_ECHAR but got %s",nc_err_code_name(err));
            ELSE_NOK
        }
    }

    /* Preceding has written nothing for record variables, now try */
    /* again with more than 0 records */

    /* Write record number NRECS to force writing of preceding records */
    /* Assumes variable cr is char vector with UNLIMITED dimension */
    err =  nc_inq_varid(ncid, "cr", &varid);
    IF (err != NC_NOERR)
        error("inq_varid: %s",  nc_strerror(err));
    index[0] = NRECS-1;
    err = nc_put_var1_text(ncid, varid, index, "x");
    IF (err != NC_NOERR)
        error("put_var1_text: %s",  nc_strerror(err));

    for (i = 0; i < numVars; i++) {
        if (var_dimid[i][0] != RECDIM) continue; /* only record variables here */

        canConvert = (var_type[i] == NC_CHAR) == (NCT_UINT == NCT_TEXT);

        for (allInExtRange = 1, j = 0; j < var_nels[i]; j++) {
            err = toMixedBase(j, var_rank[i], var_shape[i], index);
            IF (err != 0) error("error in toMixedBase");
            value[j]= hash_uint(cdf_format,var_type[i], var_rank[i], index,
                              NCT_UINT);
            
                allInExtRange &= inRange3(cdf_format, (double)value[j],
                                          var_type[i], NCT_UINT);
        }
        err = nc_put_var_uint(ncid, i, value);
        if (canConvert) {
            if (allInExtRange) {
                IF (err != NC_NOERR)
                    error("expecting NC_NOERR but got %s",nc_err_code_name(err));
                ELSE_NOK
            } else {
                IF (err != NC_ERANGE)
                    error("expecting NC_ERANGE but got %s",nc_err_code_name(err));
                ELSE_NOK
            }
        } else {
            IF (err != NC_ECHAR)
                error("expecting NC_ECHAR but got %s",nc_err_code_name(err));
            ELSE_NOK
        }
    }

    err =  nc_close(ncid);
    IF (err != NC_NOERR)
        error("close: %s",  nc_strerror(err));

    nok += check_vars_uint(scratch, numVars);

    err = nc_delete(scratch);
    IF (err != NC_NOERR)
        error("delete file %s failed", scratch);
    return nok;
}

int
test_nc_put_var_longlong(void)
{
    int i, err, ncid, varid, cdf_format, nok=0;
    int canConvert;        /* Both text or both numeric */
    int allInExtRange;     /* all values within external range? */
    size_t j, index[MAX_RANK];
    longlong value[MAX_NELS];

    err = file_create(scratch, NC_CLOBBER, &ncid);
    IF (err != NC_NOERR) {
        error("create: %s",  nc_strerror(err));
        return nok;
    }

    err =  nc_inq_format(ncid, &cdf_format);
    IF (err != NC_NOERR)
        error("inq_format: %s",  nc_strerror(err));

    def_dims(ncid);
    def_vars(ncid);

    err =  nc_enddef(ncid);
    IF (err != NC_NOERR)
        error("enddef: %s",  nc_strerror(err));

    /* check if can detect a bad file ID */
    err = nc_put_var_longlong(BAD_ID, 0, NULL);
    IF (err != NC_EBADID)
        error("expecting NC_EBADID but got %s",nc_err_code_name(err));
    ELSE_NOK

    /* check if can detect a bad variable ID */
    err = nc_put_var_longlong(ncid, BAD_VARID, NULL);
    IF (err != NC_ENOTVAR)
        error("expecting NC_ENOTVAR but got %s",nc_err_code_name(err));
    ELSE_NOK

    for (i = 0; i < numVars; i++) {
        assert(var_rank[i] <= MAX_RANK);
        assert(var_nels[i] <= MAX_NELS);

        if (var_dimid[i][0] == RECDIM) continue; /* fixed-size variables only */

        value[0] = 5;  /* reset to a value within bounds */

        /* check if can detect a bad file ID */
        err = nc_put_var_longlong(BAD_ID, i, value);
        IF (err != NC_EBADID)
            error("expecting NC_EBADID but got %s",nc_err_code_name(err));
        ELSE_NOK

        canConvert = (var_type[i] == NC_CHAR) == (NCT_LONGLONG == NCT_TEXT);

        for (allInExtRange = 1, j = 0; j < var_nels[i]; j++) {
            err = toMixedBase(j, var_rank[i], var_shape[i], index);
            IF (err != 0) error("error in toMixedBase");
            value[j]= hash_longlong(cdf_format,var_type[i], var_rank[i], index,
                              NCT_LONGLONG);
            
                allInExtRange &= inRange3(cdf_format, (double)value[j],
                                          var_type[i], NCT_LONGLONG);
        }
        err = nc_put_var_longlong(ncid, i, value);
        if (canConvert) {
            if (allInExtRange) {
                IF (err != NC_NOERR)
                    error("expecting NC_NOERR but got %s",nc_err_code_name(err));
                ELSE_NOK
            }
            
                    else {

                        IF (err != NC_ERANGE)
                            error("expecting NC_ERANGE but got %s",nc_err_code_name(err));
                        ELSE_NOK
                    }


        } else { /* should flag wrong type even if nothing to write */
            IF (err != NC_ECHAR)
                error("expecting NC_ECHAR but got %s",nc_err_code_name(err));
            ELSE_NOK
        }
    }

    /* Preceding has written nothing for record variables, now try */
    /* again with more than 0 records */

    /* Write record number NRECS to force writing of preceding records */
    /* Assumes variable cr is char vector with UNLIMITED dimension */
    err =  nc_inq_varid(ncid, "cr", &varid);
    IF (err != NC_NOERR)
        error("inq_varid: %s",  nc_strerror(err));
    index[0] = NRECS-1;
    err = nc_put_var1_text(ncid, varid, index, "x");
    IF (err != NC_NOERR)
        error("put_var1_text: %s",  nc_strerror(err));

    for (i = 0; i < numVars; i++) {
        if (var_dimid[i][0] != RECDIM) continue; /* only record variables here */

        canConvert = (var_type[i] == NC_CHAR) == (NCT_LONGLONG == NCT_TEXT);

        for (allInExtRange = 1, j = 0; j < var_nels[i]; j++) {
            err = toMixedBase(j, var_rank[i], var_shape[i], index);
            IF (err != 0) error("error in toMixedBase");
            value[j]= hash_longlong(cdf_format,var_type[i], var_rank[i], index,
                              NCT_LONGLONG);
            
                allInExtRange &= inRange3(cdf_format, (double)value[j],
                                          var_type[i], NCT_LONGLONG);
        }
        err = nc_put_var_longlong(ncid, i, value);
        if (canConvert) {
            if (allInExtRange) {
                IF (err != NC_NOERR)
                    error("expecting NC_NOERR but got %s",nc_err_code_name(err));
                ELSE_NOK
            } else {
                IF (err != NC_ERANGE)
                    error("expecting NC_ERANGE but got %s",nc_err_code_name(err));
                ELSE_NOK
            }
        } else {
            IF (err != NC_ECHAR)
                error("expecting NC_ECHAR but got %s",nc_err_code_name(err));
            ELSE_NOK
        }
    }

    err =  nc_close(ncid);
    IF (err != NC_NOERR)
        error("close: %s",  nc_strerror(err));

    nok += check_vars_longlong(scratch, numVars);

    err = nc_delete(scratch);
    IF (err != NC_NOERR)
        error("delete file %s failed", scratch);
    return nok;
}

int
test_nc_put_var_ulonglong(void)
{
    int i, err, ncid, varid, cdf_format, nok=0;
    int canConvert;        /* Both text or both numeric */
    int allInExtRange;     /* all values within external range? */
    size_t j, index[MAX_RANK];
    ulonglong value[MAX_NELS];

    err = file_create(scratch, NC_CLOBBER, &ncid);
    IF (err != NC_NOERR) {
        error("create: %s",  nc_strerror(err));
        return nok;
    }

    err =  nc_inq_format(ncid, &cdf_format);
    IF (err != NC_NOERR)
        error("inq_format: %s",  nc_strerror(err));

    def_dims(ncid);
    def_vars(ncid);

    err =  nc_enddef(ncid);
    IF (err != NC_NOERR)
        error("enddef: %s",  nc_strerror(err));

    /* check if can detect a bad file ID */
    err = nc_put_var_ulonglong(BAD_ID, 0, NULL);
    IF (err != NC_EBADID)
        error("expecting NC_EBADID but got %s",nc_err_code_name(err));
    ELSE_NOK

    /* check if can detect a bad variable ID */
    err = nc_put_var_ulonglong(ncid, BAD_VARID, NULL);
    IF (err != NC_ENOTVAR)
        error("expecting NC_ENOTVAR but got %s",nc_err_code_name(err));
    ELSE_NOK

    for (i = 0; i < numVars; i++) {
        assert(var_rank[i] <= MAX_RANK);
        assert(var_nels[i] <= MAX_NELS);

        if (var_dimid[i][0] == RECDIM) continue; /* fixed-size variables only */

        value[0] = 5;  /* reset to a value within bounds */

        /* check if can detect a bad file ID */
        err = nc_put_var_ulonglong(BAD_ID, i, value);
        IF (err != NC_EBADID)
            error("expecting NC_EBADID but got %s",nc_err_code_name(err));
        ELSE_NOK

        canConvert = (var_type[i] == NC_CHAR) == (NCT_ULONGLONG == NCT_TEXT);

        for (allInExtRange = 1, j = 0; j < var_nels[i]; j++) {
            err = toMixedBase(j, var_rank[i], var_shape[i], index);
            IF (err != 0) error("error in toMixedBase");
            value[j]= hash_ulonglong(cdf_format,var_type[i], var_rank[i], index,
                              NCT_ULONGLONG);
            
                allInExtRange &= inRange3(cdf_format, (double)value[j],
                                          var_type[i], NCT_ULONGLONG);
        }
        err = nc_put_var_ulonglong(ncid, i, value);
        if (canConvert) {
            if (allInExtRange) {
                IF (err != NC_NOERR)
                    error("expecting NC_NOERR but got %s",nc_err_code_name(err));
                ELSE_NOK
            }
            
                    else {

                        IF (err != NC_ERANGE)
                            error("expecting NC_ERANGE but got %s",nc_err_code_name(err));
                        ELSE_NOK
                    }


        } else { /* should flag wrong type even if nothing to write */
            IF (err != NC_ECHAR)
                error("expecting NC_ECHAR but got %s",nc_err_code_name(err));
            ELSE_NOK
        }
    }

    /* Preceding has written nothing for record variables, now try */
    /* again with more than 0 records */

    /* Write record number NRECS to force writing of preceding records */
    /* Assumes variable cr is char vector with UNLIMITED dimension */
    err =  nc_inq_varid(ncid, "cr", &varid);
    IF (err != NC_NOERR)
        error("inq_varid: %s",  nc_strerror(err));
    index[0] = NRECS-1;
    err = nc_put_var1_text(ncid, varid, index, "x");
    IF (err != NC_NOERR)
        error("put_var1_text: %s",  nc_strerror(err));

    for (i = 0; i < numVars; i++) {
        if (var_dimid[i][0] != RECDIM) continue; /* only record variables here */

        canConvert = (var_type[i] == NC_CHAR) == (NCT_ULONGLONG == NCT_TEXT);

        for (allInExtRange = 1, j = 0; j < var_nels[i]; j++) {
            err = toMixedBase(j, var_rank[i], var_shape[i], index);
            IF (err != 0) error("error in toMixedBase");
            value[j]= hash_ulonglong(cdf_format,var_type[i], var_rank[i], index,
                              NCT_ULONGLONG);
            
                allInExtRange &= inRange3(cdf_format, (double)value[j],
                                          var_type[i], NCT_ULONGLONG);
        }
        err = nc_put_var_ulonglong(ncid, i, value);
        if (canConvert) {
            if (allInExtRange) {
                IF (err != NC_NOERR)
                    error("expecting NC_NOERR but got %s",nc_err_code_name(err));
                ELSE_NOK
            } else {
                IF (err != NC_ERANGE)
                    error("expecting NC_ERANGE but got %s",nc_err_code_name(err));
                ELSE_NOK
            }
        } else {
            IF (err != NC_ECHAR)
                error("expecting NC_ECHAR but got %s",nc_err_code_name(err));
            ELSE_NOK
        }
    }

    err =  nc_close(ncid);
    IF (err != NC_NOERR)
        error("close: %s",  nc_strerror(err));

    nok += check_vars_ulonglong(scratch, numVars);

    err = nc_delete(scratch);
    IF (err != NC_NOERR)
        error("delete file %s failed", scratch);
    return nok;
}




int
test_nc_put_vara_text(void)
{
    int i, k, d, err, nslabs, ncid, cdf_format, nok=0;
    int canConvert;        /* Both text or both numeric */
    int allInExtRange;     /* all values within external range? */
    size_t j, nels;
    size_t start[MAX_RANK], edge[MAX_RANK];
    size_t mid[MAX_RANK], index[MAX_RANK];
    text value[MAX_NELS];

    err = file_create(scratch, NC_CLOBBER, &ncid);
    IF (err != NC_NOERR) {
        error("create: %s",  nc_strerror(err));
        return nok;
    }

    err =  nc_inq_format(ncid, &cdf_format);
    IF (err != NC_NOERR)
        error("inq_format: %s",  nc_strerror(err));

    def_dims(ncid);
    def_vars(ncid);

    err =  nc_enddef(ncid);
    IF (err != NC_NOERR)
        error("enddef: %s",  nc_strerror(err));

    /* check if can detect a bad file ID */
    err = nc_put_vara_text(BAD_ID, 0, NULL, NULL, NULL);
    IF (err != NC_EBADID)
        error("expecting NC_EBADID but got %s",nc_err_code_name(err));
    ELSE_NOK

    /* check if can detect a bad variable ID */
    err = nc_put_vara_text(ncid, BAD_VARID, NULL, NULL, NULL);
    IF (err != NC_ENOTVAR)
        error("expecting NC_ENOTVAR but got %s",nc_err_code_name(err));
    ELSE_NOK

    for (i = 0; i < numVars; i++) {
        assert(var_rank[i] <= MAX_RANK);
        assert(var_nels[i] <= MAX_NELS);

        value[0] = 5; /* reset to a value within bounds */

        /* check if can detect a bad file ID */
        err = nc_put_vara_text(BAD_ID, i, NULL, NULL, value);
        IF (err != NC_EBADID)
            error("expecting NC_EBADID but got %s",nc_err_code_name(err));
        ELSE_NOK

        canConvert = (var_type[i] == NC_CHAR) ;

        for (j = 0; j < var_rank[i]; j++) {
            start[j] = 0;
            edge[j] = 1;
        }


        /* first test when edge[*] > 0 */
        for (j = 0; j < var_rank[i]; j++) {
            if (var_dimid[i][j] == RECDIM) continue; /* skip record dim */
            start[j] = var_shape[i][j];
            err = nc_put_vara_text(ncid, i, start, edge, value);
            if (!canConvert) {
                IF (err != NC_ECHAR)
                    error("expecting NC_ECHAR but got %s",nc_err_code_name(err));
                ELSE_NOK
                start[j] = 0;
                continue;
            }
            IF (err != NC_EINVALCOORDS)
                error("expecting NC_EINVALCOORDS but got %s",nc_err_code_name(err));
            ELSE_NOK
            start[j] = 0;
            edge[j] = var_shape[i][j] + 1;
            err = nc_put_vara_text(ncid, i, start, edge, value);
            IF (err != NC_EEDGE)
                error("expecting NC_EEDG but got %s",nc_err_code_name(err));
            ELSE_NOK
            edge[j] = 1;
        }

        /* Check correct error returned when nothing to put, when edge[*]==0 */
        for (j = 0; j < var_rank[i]; j++) edge[j] = 0;

        for (j = 0; j < var_rank[i]; j++) {
            if (var_dimid[i][j] == RECDIM) continue; /* skip record dim */
            start[j] = var_shape[i][j];
            err = nc_put_vara_text(ncid, i, start, edge, value);
            if (!canConvert) {
                IF (err != NC_ECHAR)
                    error("expecting NC_ECHAR but got %s",nc_err_code_name(err));
                ELSE_NOK
                start[j] = 0;
                continue;
            }
#ifdef RELAX_COORD_BOUND
            IF (err != NC_NOERR) /* allowed when edge[j]==0 */
                error("expecting NC_NOERR but got %s",nc_err_code_name(err));
#else
            IF (err != NC_EINVALCOORDS) /* not allowed even when edge[j]==0 */
                error("expecting NC_EINVALCOORDS but got %s",nc_err_code_name(err));
#endif
            ELSE_NOK
            start[j] = var_shape[i][j]+1; /* out of boundary check */
            err = nc_put_vara_text(ncid, i, start, edge, value);
            IF (err != NC_EINVALCOORDS)
                error("expecting NC_EINVALCOORDS but got %s",nc_err_code_name(err));
            ELSE_NOK
            start[j] = 0;
        }
        for (j = 0; j < var_rank[i]; j++) edge[j] = 1;

        /* Choose a random point dividing each dim into 2 parts */
        /* Put 2^rank (nslabs) slabs so defined */
        nslabs = 1;
        for (j = 0; j < var_rank[i]; j++) {
            mid[j] = roll( var_shape[i][j] );
            nslabs *= 2;
        }
        /* bits of k determine whether to put lower or upper part of dim */
        for (k = 0; k < nslabs; k++) {
            nels = 1;
            for (j = 0; j < var_rank[i]; j++) {
                if ((k >> j) & 1) {
                    start[j] = 0;
                    edge[j] = mid[j];
                } else {
                    start[j] = mid[j];
                    edge[j] = var_shape[i][j] - mid[j];
                }
                nels *= edge[j];
            }

            for (allInExtRange = 1, j = 0; j < nels; j++) {
                err = toMixedBase(j, var_rank[i], edge, index);
                IF (err != 0) error("error in toMixedBase");
                for (d = 0; d < var_rank[i]; d++)
                    index[d] += start[d];
                value[j]= hash_text(cdf_format,var_type[i], var_rank[i], index,
                                  NCT_TEXT);
                if (var_type[i] != NC_CHAR)
                    allInExtRange &= inRange3(cdf_format, (double)value[j],
                                              var_type[i], NCT_TEXT);
            }
            err = nc_put_vara_text(ncid, i, start, edge, value);
            if (canConvert) {
                if (allInExtRange) {
                    IF (err != NC_NOERR)
                        error("expecting NC_NOERR but got %s",nc_err_code_name(err));
                    ELSE_NOK
                }
                
                    else {

                        IF (err != NC_ERANGE)
                            error("expecting NC_ERANGE but got %s",nc_err_code_name(err));
                        ELSE_NOK
                    }


            } else {
                IF (err != NC_ECHAR)
                    error("expecting NC_ECHAR but got %s",nc_err_code_name(err));
                ELSE_NOK
            }
        }
    }

    err =  nc_close(ncid);
    IF (err != NC_NOERR)
        error("close: %s",  nc_strerror(err));

    nok += check_vars_text(scratch, numVars);

    err = nc_delete(scratch);
    IF (err != NC_NOERR)
        error("delete file %s failed", scratch);
    return nok;
}

int
test_nc_put_vara_uchar(void)
{
    int i, k, d, err, nslabs, ncid, cdf_format, nok=0;
    int canConvert;        /* Both text or both numeric */
    int allInExtRange;     /* all values within external range? */
    size_t j, nels;
    size_t start[MAX_RANK], edge[MAX_RANK];
    size_t mid[MAX_RANK], index[MAX_RANK];
    uchar value[MAX_NELS];

    err = file_create(scratch, NC_CLOBBER, &ncid);
    IF (err != NC_NOERR) {
        error("create: %s",  nc_strerror(err));
        return nok;
    }

    err =  nc_inq_format(ncid, &cdf_format);
    IF (err != NC_NOERR)
        error("inq_format: %s",  nc_strerror(err));

    def_dims(ncid);
    def_vars(ncid);

    err =  nc_enddef(ncid);
    IF (err != NC_NOERR)
        error("enddef: %s",  nc_strerror(err));

    /* check if can detect a bad file ID */
    err = nc_put_vara_uchar(BAD_ID, 0, NULL, NULL, NULL);
    IF (err != NC_EBADID)
        error("expecting NC_EBADID but got %s",nc_err_code_name(err));
    ELSE_NOK

    /* check if can detect a bad variable ID */
    err = nc_put_vara_uchar(ncid, BAD_VARID, NULL, NULL, NULL);
    IF (err != NC_ENOTVAR)
        error("expecting NC_ENOTVAR but got %s",nc_err_code_name(err));
    ELSE_NOK

    for (i = 0; i < numVars; i++) {
        assert(var_rank[i] <= MAX_RANK);
        assert(var_nels[i] <= MAX_NELS);

        value[0] = 5; /* reset to a value within bounds */

        /* check if can detect a bad file ID */
        err = nc_put_vara_uchar(BAD_ID, i, NULL, NULL, value);
        IF (err != NC_EBADID)
            error("expecting NC_EBADID but got %s",nc_err_code_name(err));
        ELSE_NOK

        canConvert = (var_type[i] == NC_CHAR) == (NCT_UCHAR == NCT_TEXT);

        for (j = 0; j < var_rank[i]; j++) {
            start[j] = 0;
            edge[j] = 1;
        }


        /* first test when edge[*] > 0 */
        for (j = 0; j < var_rank[i]; j++) {
            if (var_dimid[i][j] == RECDIM) continue; /* skip record dim */
            start[j] = var_shape[i][j];
            err = nc_put_vara_uchar(ncid, i, start, edge, value);
            if (!canConvert) {
                IF (err != NC_ECHAR)
                    error("expecting NC_ECHAR but got %s",nc_err_code_name(err));
                ELSE_NOK
                start[j] = 0;
                continue;
            }
            IF (err != NC_EINVALCOORDS)
                error("expecting NC_EINVALCOORDS but got %s",nc_err_code_name(err));
            ELSE_NOK
            start[j] = 0;
            edge[j] = var_shape[i][j] + 1;
            err = nc_put_vara_uchar(ncid, i, start, edge, value);
            IF (err != NC_EEDGE)
                error("expecting NC_EEDG but got %s",nc_err_code_name(err));
            ELSE_NOK
            edge[j] = 1;
        }

        /* Check correct error returned when nothing to put, when edge[*]==0 */
        for (j = 0; j < var_rank[i]; j++) edge[j] = 0;

        for (j = 0; j < var_rank[i]; j++) {
            if (var_dimid[i][j] == RECDIM) continue; /* skip record dim */
            start[j] = var_shape[i][j];
            err = nc_put_vara_uchar(ncid, i, start, edge, value);
            if (!canConvert) {
                IF (err != NC_ECHAR)
                    error("expecting NC_ECHAR but got %s",nc_err_code_name(err));
                ELSE_NOK
                start[j] = 0;
                continue;
            }
#ifdef RELAX_COORD_BOUND
            IF (err != NC_NOERR) /* allowed when edge[j]==0 */
                error("expecting NC_NOERR but got %s",nc_err_code_name(err));
#else
            IF (err != NC_EINVALCOORDS) /* not allowed even when edge[j]==0 */
                error("expecting NC_EINVALCOORDS but got %s",nc_err_code_name(err));
#endif
            ELSE_NOK
            start[j] = var_shape[i][j]+1; /* out of boundary check */
            err = nc_put_vara_uchar(ncid, i, start, edge, value);
            IF (err != NC_EINVALCOORDS)
                error("expecting NC_EINVALCOORDS but got %s",nc_err_code_name(err));
            ELSE_NOK
            start[j] = 0;
        }
        for (j = 0; j < var_rank[i]; j++) edge[j] = 1;

        /* Choose a random point dividing each dim into 2 parts */
        /* Put 2^rank (nslabs) slabs so defined */
        nslabs = 1;
        for (j = 0; j < var_rank[i]; j++) {
            mid[j] = roll( var_shape[i][j] );
            nslabs *= 2;
        }
        /* bits of k determine whether to put lower or upper part of dim */
        for (k = 0; k < nslabs; k++) {
            nels = 1;
            for (j = 0; j < var_rank[i]; j++) {
                if ((k >> j) & 1) {
                    start[j] = 0;
                    edge[j] = mid[j];
                } else {
                    start[j] = mid[j];
                    edge[j] = var_shape[i][j] - mid[j];
                }
                nels *= edge[j];
            }

            for (allInExtRange = 1, j = 0; j < nels; j++) {
                err = toMixedBase(j, var_rank[i], edge, index);
                IF (err != 0) error("error in toMixedBase");
                for (d = 0; d < var_rank[i]; d++)
                    index[d] += start[d];
                value[j]= hash_uchar(cdf_format,var_type[i], var_rank[i], index,
                                  NCT_UCHAR);
                
                    allInExtRange &= inRange3(cdf_format, (double)value[j],
                                              var_type[i], NCT_UCHAR);
            }
            err = nc_put_vara_uchar(ncid, i, start, edge, value);
            if (canConvert) {
                if (allInExtRange) {
                    IF (err != NC_NOERR)
                        error("expecting NC_NOERR but got %s",nc_err_code_name(err));
                    ELSE_NOK
                }
                
#if !defined(USE_PNETCDF) || (PNETCDF_VERSION_MAJOR==1 && PNETCDF_VERSION_MINOR>=8)
                    else {

                        IF (err != NC_ERANGE)
                            error("expecting NC_ERANGE but got %s",nc_err_code_name(err));
                        ELSE_NOK
                    }
#endif

            } else {
                IF (err != NC_ECHAR)
                    error("expecting NC_ECHAR but got %s",nc_err_code_name(err));
                ELSE_NOK
            }
        }
    }

    err =  nc_close(ncid);
    IF (err != NC_NOERR)
        error("close: %s",  nc_strerror(err));

    nok += check_vars_uchar(scratch, numVars);

    err = nc_delete(scratch);
    IF (err != NC_NOERR)
        error("delete file %s failed", scratch);
    return nok;
}

int
test_nc_put_vara_schar(void)
{
    int i, k, d, err, nslabs, ncid, cdf_format, nok=0;
    int canConvert;        /* Both text or both numeric */
    int allInExtRange;     /* all values within external range? */
    size_t j, nels;
    size_t start[MAX_RANK], edge[MAX_RANK];
    size_t mid[MAX_RANK], index[MAX_RANK];
    schar value[MAX_NELS];

    err = file_create(scratch, NC_CLOBBER, &ncid);
    IF (err != NC_NOERR) {
        error("create: %s",  nc_strerror(err));
        return nok;
    }

    err =  nc_inq_format(ncid, &cdf_format);
    IF (err != NC_NOERR)
        error("inq_format: %s",  nc_strerror(err));

    def_dims(ncid);
    def_vars(ncid);

    err =  nc_enddef(ncid);
    IF (err != NC_NOERR)
        error("enddef: %s",  nc_strerror(err));

    /* check if can detect a bad file ID */
    err = nc_put_vara_schar(BAD_ID, 0, NULL, NULL, NULL);
    IF (err != NC_EBADID)
        error("expecting NC_EBADID but got %s",nc_err_code_name(err));
    ELSE_NOK

    /* check if can detect a bad variable ID */
    err = nc_put_vara_schar(ncid, BAD_VARID, NULL, NULL, NULL);
    IF (err != NC_ENOTVAR)
        error("expecting NC_ENOTVAR but got %s",nc_err_code_name(err));
    ELSE_NOK

    for (i = 0; i < numVars; i++) {
        assert(var_rank[i] <= MAX_RANK);
        assert(var_nels[i] <= MAX_NELS);

        value[0] = 5; /* reset to a value within bounds */

        /* check if can detect a bad file ID */
        err = nc_put_vara_schar(BAD_ID, i, NULL, NULL, value);
        IF (err != NC_EBADID)
            error("expecting NC_EBADID but got %s",nc_err_code_name(err));
        ELSE_NOK

        canConvert = (var_type[i] == NC_CHAR) == (NCT_SCHAR == NCT_TEXT);

        for (j = 0; j < var_rank[i]; j++) {
            start[j] = 0;
            edge[j] = 1;
        }


        /* first test when edge[*] > 0 */
        for (j = 0; j < var_rank[i]; j++) {
            if (var_dimid[i][j] == RECDIM) continue; /* skip record dim */
            start[j] = var_shape[i][j];
            err = nc_put_vara_schar(ncid, i, start, edge, value);
            if (!canConvert) {
                IF (err != NC_ECHAR)
                    error("expecting NC_ECHAR but got %s",nc_err_code_name(err));
                ELSE_NOK
                start[j] = 0;
                continue;
            }
            IF (err != NC_EINVALCOORDS)
                error("expecting NC_EINVALCOORDS but got %s",nc_err_code_name(err));
            ELSE_NOK
            start[j] = 0;
            edge[j] = var_shape[i][j] + 1;
            err = nc_put_vara_schar(ncid, i, start, edge, value);
            IF (err != NC_EEDGE)
                error("expecting NC_EEDG but got %s",nc_err_code_name(err));
            ELSE_NOK
            edge[j] = 1;
        }

        /* Check correct error returned when nothing to put, when edge[*]==0 */
        for (j = 0; j < var_rank[i]; j++) edge[j] = 0;

        for (j = 0; j < var_rank[i]; j++) {
            if (var_dimid[i][j] == RECDIM) continue; /* skip record dim */
            start[j] = var_shape[i][j];
            err = nc_put_vara_schar(ncid, i, start, edge, value);
            if (!canConvert) {
                IF (err != NC_ECHAR)
                    error("expecting NC_ECHAR but got %s",nc_err_code_name(err));
                ELSE_NOK
                start[j] = 0;
                continue;
            }
#ifdef RELAX_COORD_BOUND
            IF (err != NC_NOERR) /* allowed when edge[j]==0 */
                error("expecting NC_NOERR but got %s",nc_err_code_name(err));
#else
            IF (err != NC_EINVALCOORDS) /* not allowed even when edge[j]==0 */
                error("expecting NC_EINVALCOORDS but got %s",nc_err_code_name(err));
#endif
            ELSE_NOK
            start[j] = var_shape[i][j]+1; /* out of boundary check */
            err = nc_put_vara_schar(ncid, i, start, edge, value);
            IF (err != NC_EINVALCOORDS)
                error("expecting NC_EINVALCOORDS but got %s",nc_err_code_name(err));
            ELSE_NOK
            start[j] = 0;
        }
        for (j = 0; j < var_rank[i]; j++) edge[j] = 1;

        /* Choose a random point dividing each dim into 2 parts */
        /* Put 2^rank (nslabs) slabs so defined */
        nslabs = 1;
        for (j = 0; j < var_rank[i]; j++) {
            mid[j] = roll( var_shape[i][j] );
            nslabs *= 2;
        }
        /* bits of k determine whether to put lower or upper part of dim */
        for (k = 0; k < nslabs; k++) {
            nels = 1;
            for (j = 0; j < var_rank[i]; j++) {
                if ((k >> j) & 1) {
                    start[j] = 0;
                    edge[j] = mid[j];
                } else {
                    start[j] = mid[j];
                    edge[j] = var_shape[i][j] - mid[j];
                }
                nels *= edge[j];
            }

            for (allInExtRange = 1, j = 0; j < nels; j++) {
                err = toMixedBase(j, var_rank[i], edge, index);
                IF (err != 0) error("error in toMixedBase");
                for (d = 0; d < var_rank[i]; d++)
                    index[d] += start[d];
                value[j]= hash_schar(cdf_format,var_type[i], var_rank[i], index,
                                  NCT_SCHAR);
                
                    allInExtRange &= inRange3(cdf_format, (double)value[j],
                                              var_type[i], NCT_SCHAR);
            }
            err = nc_put_vara_schar(ncid, i, start, edge, value);
            if (canConvert) {
                if (allInExtRange) {
                    IF (err != NC_NOERR)
                        error("expecting NC_NOERR but got %s",nc_err_code_name(err));
                    ELSE_NOK
                }
                
#if defined(USE_PNETCDF) && PNETCDF_VERSION_MAJOR==1 && PNETCDF_VERSION_MINOR<7
                    else if (cdf_format < NC_FORMAT_CDF5) {
#else
                    else {
#endif
                        IF (err != NC_ERANGE)
                            error("expecting NC_ERANGE but got %s",nc_err_code_name(err));
                        ELSE_NOK
                    }


            } else {
                IF (err != NC_ECHAR)
                    error("expecting NC_ECHAR but got %s",nc_err_code_name(err));
                ELSE_NOK
            }
        }
    }

    err =  nc_close(ncid);
    IF (err != NC_NOERR)
        error("close: %s",  nc_strerror(err));

    nok += check_vars_schar(scratch, numVars);

    err = nc_delete(scratch);
    IF (err != NC_NOERR)
        error("delete file %s failed", scratch);
    return nok;
}

int
test_nc_put_vara_short(void)
{
    int i, k, d, err, nslabs, ncid, cdf_format, nok=0;
    int canConvert;        /* Both text or both numeric */
    int allInExtRange;     /* all values within external range? */
    size_t j, nels;
    size_t start[MAX_RANK], edge[MAX_RANK];
    size_t mid[MAX_RANK], index[MAX_RANK];
    short value[MAX_NELS];

    err = file_create(scratch, NC_CLOBBER, &ncid);
    IF (err != NC_NOERR) {
        error("create: %s",  nc_strerror(err));
        return nok;
    }

    err =  nc_inq_format(ncid, &cdf_format);
    IF (err != NC_NOERR)
        error("inq_format: %s",  nc_strerror(err));

    def_dims(ncid);
    def_vars(ncid);

    err =  nc_enddef(ncid);
    IF (err != NC_NOERR)
        error("enddef: %s",  nc_strerror(err));

    /* check if can detect a bad file ID */
    err = nc_put_vara_short(BAD_ID, 0, NULL, NULL, NULL);
    IF (err != NC_EBADID)
        error("expecting NC_EBADID but got %s",nc_err_code_name(err));
    ELSE_NOK

    /* check if can detect a bad variable ID */
    err = nc_put_vara_short(ncid, BAD_VARID, NULL, NULL, NULL);
    IF (err != NC_ENOTVAR)
        error("expecting NC_ENOTVAR but got %s",nc_err_code_name(err));
    ELSE_NOK

    for (i = 0; i < numVars; i++) {
        assert(var_rank[i] <= MAX_RANK);
        assert(var_nels[i] <= MAX_NELS);

        value[0] = 5; /* reset to a value within bounds */

        /* check if can detect a bad file ID */
        err = nc_put_vara_short(BAD_ID, i, NULL, NULL, value);
        IF (err != NC_EBADID)
            error("expecting NC_EBADID but got %s",nc_err_code_name(err));
        ELSE_NOK

        canConvert = (var_type[i] == NC_CHAR) == (NCT_SHORT == NCT_TEXT);

        for (j = 0; j < var_rank[i]; j++) {
            start[j] = 0;
            edge[j] = 1;
        }


        /* first test when edge[*] > 0 */
        for (j = 0; j < var_rank[i]; j++) {
            if (var_dimid[i][j] == RECDIM) continue; /* skip record dim */
            start[j] = var_shape[i][j];
            err = nc_put_vara_short(ncid, i, start, edge, value);
            if (!canConvert) {
                IF (err != NC_ECHAR)
                    error("expecting NC_ECHAR but got %s",nc_err_code_name(err));
                ELSE_NOK
                start[j] = 0;
                continue;
            }
            IF (err != NC_EINVALCOORDS)
                error("expecting NC_EINVALCOORDS but got %s",nc_err_code_name(err));
            ELSE_NOK
            start[j] = 0;
            edge[j] = var_shape[i][j] + 1;
            err = nc_put_vara_short(ncid, i, start, edge, value);
            IF (err != NC_EEDGE)
                error("expecting NC_EEDG but got %s",nc_err_code_name(err));
            ELSE_NOK
            edge[j] = 1;
        }

        /* Check correct error returned when nothing to put, when edge[*]==0 */
        for (j = 0; j < var_rank[i]; j++) edge[j] = 0;

        for (j = 0; j < var_rank[i]; j++) {
            if (var_dimid[i][j] == RECDIM) continue; /* skip record dim */
            start[j] = var_shape[i][j];
            err = nc_put_vara_short(ncid, i, start, edge, value);
            if (!canConvert) {
                IF (err != NC_ECHAR)
                    error("expecting NC_ECHAR but got %s",nc_err_code_name(err));
                ELSE_NOK
                start[j] = 0;
                continue;
            }
#ifdef RELAX_COORD_BOUND
            IF (err != NC_NOERR) /* allowed when edge[j]==0 */
                error("expecting NC_NOERR but got %s",nc_err_code_name(err));
#else
            IF (err != NC_EINVALCOORDS) /* not allowed even when edge[j]==0 */
                error("expecting NC_EINVALCOORDS but got %s",nc_err_code_name(err));
#endif
            ELSE_NOK
            start[j] = var_shape[i][j]+1; /* out of boundary check */
            err = nc_put_vara_short(ncid, i, start, edge, value);
            IF (err != NC_EINVALCOORDS)
                error("expecting NC_EINVALCOORDS but got %s",nc_err_code_name(err));
            ELSE_NOK
            start[j] = 0;
        }
        for (j = 0; j < var_rank[i]; j++) edge[j] = 1;

        /* Choose a random point dividing each dim into 2 parts */
        /* Put 2^rank (nslabs) slabs so defined */
        nslabs = 1;
        for (j = 0; j < var_rank[i]; j++) {
            mid[j] = roll( var_shape[i][j] );
            nslabs *= 2;
        }
        /* bits of k determine whether to put lower or upper part of dim */
        for (k = 0; k < nslabs; k++) {
            nels = 1;
            for (j = 0; j < var_rank[i]; j++) {
                if ((k >> j) & 1) {
                    start[j] = 0;
                    edge[j] = mid[j];
                } else {
                    start[j] = mid[j];
                    edge[j] = var_shape[i][j] - mid[j];
                }
                nels *= edge[j];
            }

            for (allInExtRange = 1, j = 0; j < nels; j++) {
                err = toMixedBase(j, var_rank[i], edge, index);
                IF (err != 0) error("error in toMixedBase");
                for (d = 0; d < var_rank[i]; d++)
                    index[d] += start[d];
                value[j]= hash_short(cdf_format,var_type[i], var_rank[i], index,
                                  NCT_SHORT);
                
                    allInExtRange &= inRange3(cdf_format, (double)value[j],
                                              var_type[i], NCT_SHORT);
            }
            err = nc_put_vara_short(ncid, i, start, edge, value);
            if (canConvert) {
                if (allInExtRange) {
                    IF (err != NC_NOERR)
                        error("expecting NC_NOERR but got %s",nc_err_code_name(err));
                    ELSE_NOK
                }
                
                    else {

                        IF (err != NC_ERANGE)
                            error("expecting NC_ERANGE but got %s",nc_err_code_name(err));
                        ELSE_NOK
                    }


            } else {
                IF (err != NC_ECHAR)
                    error("expecting NC_ECHAR but got %s",nc_err_code_name(err));
                ELSE_NOK
            }
        }
    }

    err =  nc_close(ncid);
    IF (err != NC_NOERR)
        error("close: %s",  nc_strerror(err));

    nok += check_vars_short(scratch, numVars);

    err = nc_delete(scratch);
    IF (err != NC_NOERR)
        error("delete file %s failed", scratch);
    return nok;
}

int
test_nc_put_vara_int(void)
{
    int i, k, d, err, nslabs, ncid, cdf_format, nok=0;
    int canConvert;        /* Both text or both numeric */
    int allInExtRange;     /* all values within external range? */
    size_t j, nels;
    size_t start[MAX_RANK], edge[MAX_RANK];
    size_t mid[MAX_RANK], index[MAX_RANK];
    int value[MAX_NELS];

    err = file_create(scratch, NC_CLOBBER, &ncid);
    IF (err != NC_NOERR) {
        error("create: %s",  nc_strerror(err));
        return nok;
    }

    err =  nc_inq_format(ncid, &cdf_format);
    IF (err != NC_NOERR)
        error("inq_format: %s",  nc_strerror(err));

    def_dims(ncid);
    def_vars(ncid);

    err =  nc_enddef(ncid);
    IF (err != NC_NOERR)
        error("enddef: %s",  nc_strerror(err));

    /* check if can detect a bad file ID */
    err = nc_put_vara_int(BAD_ID, 0, NULL, NULL, NULL);
    IF (err != NC_EBADID)
        error("expecting NC_EBADID but got %s",nc_err_code_name(err));
    ELSE_NOK

    /* check if can detect a bad variable ID */
    err = nc_put_vara_int(ncid, BAD_VARID, NULL, NULL, NULL);
    IF (err != NC_ENOTVAR)
        error("expecting NC_ENOTVAR but got %s",nc_err_code_name(err));
    ELSE_NOK

    for (i = 0; i < numVars; i++) {
        assert(var_rank[i] <= MAX_RANK);
        assert(var_nels[i] <= MAX_NELS);

        value[0] = 5; /* reset to a value within bounds */

        /* check if can detect a bad file ID */
        err = nc_put_vara_int(BAD_ID, i, NULL, NULL, value);
        IF (err != NC_EBADID)
            error("expecting NC_EBADID but got %s",nc_err_code_name(err));
        ELSE_NOK

        canConvert = (var_type[i] == NC_CHAR) == (NCT_INT == NCT_TEXT);

        for (j = 0; j < var_rank[i]; j++) {
            start[j] = 0;
            edge[j] = 1;
        }


        /* first test when edge[*] > 0 */
        for (j = 0; j < var_rank[i]; j++) {
            if (var_dimid[i][j] == RECDIM) continue; /* skip record dim */
            start[j] = var_shape[i][j];
            err = nc_put_vara_int(ncid, i, start, edge, value);
            if (!canConvert) {
                IF (err != NC_ECHAR)
                    error("expecting NC_ECHAR but got %s",nc_err_code_name(err));
                ELSE_NOK
                start[j] = 0;
                continue;
            }
            IF (err != NC_EINVALCOORDS)
                error("expecting NC_EINVALCOORDS but got %s",nc_err_code_name(err));
            ELSE_NOK
            start[j] = 0;
            edge[j] = var_shape[i][j] + 1;
            err = nc_put_vara_int(ncid, i, start, edge, value);
            IF (err != NC_EEDGE)
                error("expecting NC_EEDG but got %s",nc_err_code_name(err));
            ELSE_NOK
            edge[j] = 1;
        }

        /* Check correct error returned when nothing to put, when edge[*]==0 */
        for (j = 0; j < var_rank[i]; j++) edge[j] = 0;

        for (j = 0; j < var_rank[i]; j++) {
            if (var_dimid[i][j] == RECDIM) continue; /* skip record dim */
            start[j] = var_shape[i][j];
            err = nc_put_vara_int(ncid, i, start, edge, value);
            if (!canConvert) {
                IF (err != NC_ECHAR)
                    error("expecting NC_ECHAR but got %s",nc_err_code_name(err));
                ELSE_NOK
                start[j] = 0;
                continue;
            }
#ifdef RELAX_COORD_BOUND
            IF (err != NC_NOERR) /* allowed when edge[j]==0 */
                error("expecting NC_NOERR but got %s",nc_err_code_name(err));
#else
            IF (err != NC_EINVALCOORDS) /* not allowed even when edge[j]==0 */
                error("expecting NC_EINVALCOORDS but got %s",nc_err_code_name(err));
#endif
            ELSE_NOK
            start[j] = var_shape[i][j]+1; /* out of boundary check */
            err = nc_put_vara_int(ncid, i, start, edge, value);
            IF (err != NC_EINVALCOORDS)
                error("expecting NC_EINVALCOORDS but got %s",nc_err_code_name(err));
            ELSE_NOK
            start[j] = 0;
        }
        for (j = 0; j < var_rank[i]; j++) edge[j] = 1;

        /* Choose a random point dividing each dim into 2 parts */
        /* Put 2^rank (nslabs) slabs so defined */
        nslabs = 1;
        for (j = 0; j < var_rank[i]; j++) {
            mid[j] = roll( var_shape[i][j] );
            nslabs *= 2;
        }
        /* bits of k determine whether to put lower or upper part of dim */
        for (k = 0; k < nslabs; k++) {
            nels = 1;
            for (j = 0; j < var_rank[i]; j++) {
                if ((k >> j) & 1) {
                    start[j] = 0;
                    edge[j] = mid[j];
                } else {
                    start[j] = mid[j];
                    edge[j] = var_shape[i][j] - mid[j];
                }
                nels *= edge[j];
            }

            for (allInExtRange = 1, j = 0; j < nels; j++) {
                err = toMixedBase(j, var_rank[i], edge, index);
                IF (err != 0) error("error in toMixedBase");
                for (d = 0; d < var_rank[i]; d++)
                    index[d] += start[d];
                value[j]= hash_int(cdf_format,var_type[i], var_rank[i], index,
                                  NCT_INT);
                
                    allInExtRange &= inRange3(cdf_format, (double)value[j],
                                              var_type[i], NCT_INT);
            }
            err = nc_put_vara_int(ncid, i, start, edge, value);
            if (canConvert) {
                if (allInExtRange) {
                    IF (err != NC_NOERR)
                        error("expecting NC_NOERR but got %s",nc_err_code_name(err));
                    ELSE_NOK
                }
                
                    else {

                        IF (err != NC_ERANGE)
                            error("expecting NC_ERANGE but got %s",nc_err_code_name(err));
                        ELSE_NOK
                    }


            } else {
                IF (err != NC_ECHAR)
                    error("expecting NC_ECHAR but got %s",nc_err_code_name(err));
                ELSE_NOK
            }
        }
    }

    err =  nc_close(ncid);
    IF (err != NC_NOERR)
        error("close: %s",  nc_strerror(err));

    nok += check_vars_int(scratch, numVars);

    err = nc_delete(scratch);
    IF (err != NC_NOERR)
        error("delete file %s failed", scratch);
    return nok;
}

int
test_nc_put_vara_long(void)
{
    int i, k, d, err, nslabs, ncid, cdf_format, nok=0;
    int canConvert;        /* Both text or both numeric */
    int allInExtRange;     /* all values within external range? */
    size_t j, nels;
    size_t start[MAX_RANK], edge[MAX_RANK];
    size_t mid[MAX_RANK], index[MAX_RANK];
    long value[MAX_NELS];

    err = file_create(scratch, NC_CLOBBER, &ncid);
    IF (err != NC_NOERR) {
        error("create: %s",  nc_strerror(err));
        return nok;
    }

    err =  nc_inq_format(ncid, &cdf_format);
    IF (err != NC_NOERR)
        error("inq_format: %s",  nc_strerror(err));

    def_dims(ncid);
    def_vars(ncid);

    err =  nc_enddef(ncid);
    IF (err != NC_NOERR)
        error("enddef: %s",  nc_strerror(err));

    /* check if can detect a bad file ID */
    err = nc_put_vara_long(BAD_ID, 0, NULL, NULL, NULL);
    IF (err != NC_EBADID)
        error("expecting NC_EBADID but got %s",nc_err_code_name(err));
    ELSE_NOK

    /* check if can detect a bad variable ID */
    err = nc_put_vara_long(ncid, BAD_VARID, NULL, NULL, NULL);
    IF (err != NC_ENOTVAR)
        error("expecting NC_ENOTVAR but got %s",nc_err_code_name(err));
    ELSE_NOK

    for (i = 0; i < numVars; i++) {
        assert(var_rank[i] <= MAX_RANK);
        assert(var_nels[i] <= MAX_NELS);

        value[0] = 5; /* reset to a value within bounds */

        /* check if can detect a bad file ID */
        err = nc_put_vara_long(BAD_ID, i, NULL, NULL, value);
        IF (err != NC_EBADID)
            error("expecting NC_EBADID but got %s",nc_err_code_name(err));
        ELSE_NOK

        canConvert = (var_type[i] == NC_CHAR) == (NCT_LONG == NCT_TEXT);

        for (j = 0; j < var_rank[i]; j++) {
            start[j] = 0;
            edge[j] = 1;
        }


        /* first test when edge[*] > 0 */
        for (j = 0; j < var_rank[i]; j++) {
            if (var_dimid[i][j] == RECDIM) continue; /* skip record dim */
            start[j] = var_shape[i][j];
            err = nc_put_vara_long(ncid, i, start, edge, value);
            if (!canConvert) {
                IF (err != NC_ECHAR)
                    error("expecting NC_ECHAR but got %s",nc_err_code_name(err));
                ELSE_NOK
                start[j] = 0;
                continue;
            }
            IF (err != NC_EINVALCOORDS)
                error("expecting NC_EINVALCOORDS but got %s",nc_err_code_name(err));
            ELSE_NOK
            start[j] = 0;
            edge[j] = var_shape[i][j] + 1;
            err = nc_put_vara_long(ncid, i, start, edge, value);
            IF (err != NC_EEDGE)
                error("expecting NC_EEDG but got %s",nc_err_code_name(err));
            ELSE_NOK
            edge[j] = 1;
        }

        /* Check correct error returned when nothing to put, when edge[*]==0 */
        for (j = 0; j < var_rank[i]; j++) edge[j] = 0;

        for (j = 0; j < var_rank[i]; j++) {
            if (var_dimid[i][j] == RECDIM) continue; /* skip record dim */
            start[j] = var_shape[i][j];
            err = nc_put_vara_long(ncid, i, start, edge, value);
            if (!canConvert) {
                IF (err != NC_ECHAR)
                    error("expecting NC_ECHAR but got %s",nc_err_code_name(err));
                ELSE_NOK
                start[j] = 0;
                continue;
            }
#ifdef RELAX_COORD_BOUND
            IF (err != NC_NOERR) /* allowed when edge[j]==0 */
                error("expecting NC_NOERR but got %s",nc_err_code_name(err));
#else
            IF (err != NC_EINVALCOORDS) /* not allowed even when edge[j]==0 */
                error("expecting NC_EINVALCOORDS but got %s",nc_err_code_name(err));
#endif
            ELSE_NOK
            start[j] = var_shape[i][j]+1; /* out of boundary check */
            err = nc_put_vara_long(ncid, i, start, edge, value);
            IF (err != NC_EINVALCOORDS)
                error("expecting NC_EINVALCOORDS but got %s",nc_err_code_name(err));
            ELSE_NOK
            start[j] = 0;
        }
        for (j = 0; j < var_rank[i]; j++) edge[j] = 1;

        /* Choose a random point dividing each dim into 2 parts */
        /* Put 2^rank (nslabs) slabs so defined */
        nslabs = 1;
        for (j = 0; j < var_rank[i]; j++) {
            mid[j] = roll( var_shape[i][j] );
            nslabs *= 2;
        }
        /* bits of k determine whether to put lower or upper part of dim */
        for (k = 0; k < nslabs; k++) {
            nels = 1;
            for (j = 0; j < var_rank[i]; j++) {
                if ((k >> j) & 1) {
                    start[j] = 0;
                    edge[j] = mid[j];
                } else {
                    start[j] = mid[j];
                    edge[j] = var_shape[i][j] - mid[j];
                }
                nels *= edge[j];
            }

            for (allInExtRange = 1, j = 0; j < nels; j++) {
                err = toMixedBase(j, var_rank[i], edge, index);
                IF (err != 0) error("error in toMixedBase");
                for (d = 0; d < var_rank[i]; d++)
                    index[d] += start[d];
                value[j]= hash_long(cdf_format,var_type[i], var_rank[i], index,
                                  NCT_LONG);
                
                    allInExtRange &= inRange3(cdf_format, (double)value[j],
                                              var_type[i], NCT_LONG);
            }
            err = nc_put_vara_long(ncid, i, start, edge, value);
            if (canConvert) {
                if (allInExtRange) {
                    IF (err != NC_NOERR)
                        error("expecting NC_NOERR but got %s",nc_err_code_name(err));
                    ELSE_NOK
                }
                
                    else {

                        IF (err != NC_ERANGE)
                            error("expecting NC_ERANGE but got %s",nc_err_code_name(err));
                        ELSE_NOK
                    }


            } else {
                IF (err != NC_ECHAR)
                    error("expecting NC_ECHAR but got %s",nc_err_code_name(err));
                ELSE_NOK
            }
        }
    }

    err =  nc_close(ncid);
    IF (err != NC_NOERR)
        error("close: %s",  nc_strerror(err));

    nok += check_vars_long(scratch, numVars);

    err = nc_delete(scratch);
    IF (err != NC_NOERR)
        error("delete file %s failed", scratch);
    return nok;
}

int
test_nc_put_vara_float(void)
{
    int i, k, d, err, nslabs, ncid, cdf_format, nok=0;
    int canConvert;        /* Both text or both numeric */
    int allInExtRange;     /* all values within external range? */
    size_t j, nels;
    size_t start[MAX_RANK], edge[MAX_RANK];
    size_t mid[MAX_RANK], index[MAX_RANK];
    float value[MAX_NELS];

    err = file_create(scratch, NC_CLOBBER, &ncid);
    IF (err != NC_NOERR) {
        error("create: %s",  nc_strerror(err));
        return nok;
    }

    err =  nc_inq_format(ncid, &cdf_format);
    IF (err != NC_NOERR)
        error("inq_format: %s",  nc_strerror(err));

    def_dims(ncid);
    def_vars(ncid);

    err =  nc_enddef(ncid);
    IF (err != NC_NOERR)
        error("enddef: %s",  nc_strerror(err));

    /* check if can detect a bad file ID */
    err = nc_put_vara_float(BAD_ID, 0, NULL, NULL, NULL);
    IF (err != NC_EBADID)
        error("expecting NC_EBADID but got %s",nc_err_code_name(err));
    ELSE_NOK

    /* check if can detect a bad variable ID */
    err = nc_put_vara_float(ncid, BAD_VARID, NULL, NULL, NULL);
    IF (err != NC_ENOTVAR)
        error("expecting NC_ENOTVAR but got %s",nc_err_code_name(err));
    ELSE_NOK

    for (i = 0; i < numVars; i++) {
        assert(var_rank[i] <= MAX_RANK);
        assert(var_nels[i] <= MAX_NELS);

        value[0] = 5; /* reset to a value within bounds */

        /* check if can detect a bad file ID */
        err = nc_put_vara_float(BAD_ID, i, NULL, NULL, value);
        IF (err != NC_EBADID)
            error("expecting NC_EBADID but got %s",nc_err_code_name(err));
        ELSE_NOK

        canConvert = (var_type[i] == NC_CHAR) == (NCT_FLOAT == NCT_TEXT);

        for (j = 0; j < var_rank[i]; j++) {
            start[j] = 0;
            edge[j] = 1;
        }


        /* first test when edge[*] > 0 */
        for (j = 0; j < var_rank[i]; j++) {
            if (var_dimid[i][j] == RECDIM) continue; /* skip record dim */
            start[j] = var_shape[i][j];
            err = nc_put_vara_float(ncid, i, start, edge, value);
            if (!canConvert) {
                IF (err != NC_ECHAR)
                    error("expecting NC_ECHAR but got %s",nc_err_code_name(err));
                ELSE_NOK
                start[j] = 0;
                continue;
            }
            IF (err != NC_EINVALCOORDS)
                error("expecting NC_EINVALCOORDS but got %s",nc_err_code_name(err));
            ELSE_NOK
            start[j] = 0;
            edge[j] = var_shape[i][j] + 1;
            err = nc_put_vara_float(ncid, i, start, edge, value);
            IF (err != NC_EEDGE)
                error("expecting NC_EEDG but got %s",nc_err_code_name(err));
            ELSE_NOK
            edge[j] = 1;
        }

        /* Check correct error returned when nothing to put, when edge[*]==0 */
        for (j = 0; j < var_rank[i]; j++) edge[j] = 0;

        for (j = 0; j < var_rank[i]; j++) {
            if (var_dimid[i][j] == RECDIM) continue; /* skip record dim */
            start[j] = var_shape[i][j];
            err = nc_put_vara_float(ncid, i, start, edge, value);
            if (!canConvert) {
                IF (err != NC_ECHAR)
                    error("expecting NC_ECHAR but got %s",nc_err_code_name(err));
                ELSE_NOK
                start[j] = 0;
                continue;
            }
#ifdef RELAX_COORD_BOUND
            IF (err != NC_NOERR) /* allowed when edge[j]==0 */
                error("expecting NC_NOERR but got %s",nc_err_code_name(err));
#else
            IF (err != NC_EINVALCOORDS) /* not allowed even when edge[j]==0 */
                error("expecting NC_EINVALCOORDS but got %s",nc_err_code_name(err));
#endif
            ELSE_NOK
            start[j] = var_shape[i][j]+1; /* out of boundary check */
            err = nc_put_vara_float(ncid, i, start, edge, value);
            IF (err != NC_EINVALCOORDS)
                error("expecting NC_EINVALCOORDS but got %s",nc_err_code_name(err));
            ELSE_NOK
            start[j] = 0;
        }
        for (j = 0; j < var_rank[i]; j++) edge[j] = 1;

        /* Choose a random point dividing each dim into 2 parts */
        /* Put 2^rank (nslabs) slabs so defined */
        nslabs = 1;
        for (j = 0; j < var_rank[i]; j++) {
            mid[j] = roll( var_shape[i][j] );
            nslabs *= 2;
        }
        /* bits of k determine whether to put lower or upper part of dim */
        for (k = 0; k < nslabs; k++) {
            nels = 1;
            for (j = 0; j < var_rank[i]; j++) {
                if ((k >> j) & 1) {
                    start[j] = 0;
                    edge[j] = mid[j];
                } else {
                    start[j] = mid[j];
                    edge[j] = var_shape[i][j] - mid[j];
                }
                nels *= edge[j];
            }

            for (allInExtRange = 1, j = 0; j < nels; j++) {
                err = toMixedBase(j, var_rank[i], edge, index);
                IF (err != 0) error("error in toMixedBase");
                for (d = 0; d < var_rank[i]; d++)
                    index[d] += start[d];
                value[j]= hash_float(cdf_format,var_type[i], var_rank[i], index,
                                  NCT_FLOAT);
                
                    allInExtRange &= inRange3(cdf_format, (double)value[j],
                                              var_type[i], NCT_FLOAT);
            }
            err = nc_put_vara_float(ncid, i, start, edge, value);
            if (canConvert) {
                if (allInExtRange) {
                    IF (err != NC_NOERR)
                        error("expecting NC_NOERR but got %s",nc_err_code_name(err));
                    ELSE_NOK
                }
                
                    else {

                        IF (err != NC_ERANGE)
                            error("expecting NC_ERANGE but got %s",nc_err_code_name(err));
                        ELSE_NOK
                    }


            } else {
                IF (err != NC_ECHAR)
                    error("expecting NC_ECHAR but got %s",nc_err_code_name(err));
                ELSE_NOK
            }
        }
    }

    err =  nc_close(ncid);
    IF (err != NC_NOERR)
        error("close: %s",  nc_strerror(err));

    nok += check_vars_float(scratch, numVars);

    err = nc_delete(scratch);
    IF (err != NC_NOERR)
        error("delete file %s failed", scratch);
    return nok;
}

int
test_nc_put_vara_double(void)
{
    int i, k, d, err, nslabs, ncid, cdf_format, nok=0;
    int canConvert;        /* Both text or both numeric */
    int allInExtRange;     /* all values within external range? */
    size_t j, nels;
    size_t start[MAX_RANK], edge[MAX_RANK];
    size_t mid[MAX_RANK], index[MAX_RANK];
    double value[MAX_NELS];

    err = file_create(scratch, NC_CLOBBER, &ncid);
    IF (err != NC_NOERR) {
        error("create: %s",  nc_strerror(err));
        return nok;
    }

    err =  nc_inq_format(ncid, &cdf_format);
    IF (err != NC_NOERR)
        error("inq_format: %s",  nc_strerror(err));

    def_dims(ncid);
    def_vars(ncid);

    err =  nc_enddef(ncid);
    IF (err != NC_NOERR)
        error("enddef: %s",  nc_strerror(err));

    /* check if can detect a bad file ID */
    err = nc_put_vara_double(BAD_ID, 0, NULL, NULL, NULL);
    IF (err != NC_EBADID)
        error("expecting NC_EBADID but got %s",nc_err_code_name(err));
    ELSE_NOK

    /* check if can detect a bad variable ID */
    err = nc_put_vara_double(ncid, BAD_VARID, NULL, NULL, NULL);
    IF (err != NC_ENOTVAR)
        error("expecting NC_ENOTVAR but got %s",nc_err_code_name(err));
    ELSE_NOK

    for (i = 0; i < numVars; i++) {
        assert(var_rank[i] <= MAX_RANK);
        assert(var_nels[i] <= MAX_NELS);

        value[0] = 5; /* reset to a value within bounds */

        /* check if can detect a bad file ID */
        err = nc_put_vara_double(BAD_ID, i, NULL, NULL, value);
        IF (err != NC_EBADID)
            error("expecting NC_EBADID but got %s",nc_err_code_name(err));
        ELSE_NOK

        canConvert = (var_type[i] == NC_CHAR) == (NCT_DOUBLE == NCT_TEXT);

        for (j = 0; j < var_rank[i]; j++) {
            start[j] = 0;
            edge[j] = 1;
        }


        /* first test when edge[*] > 0 */
        for (j = 0; j < var_rank[i]; j++) {
            if (var_dimid[i][j] == RECDIM) continue; /* skip record dim */
            start[j] = var_shape[i][j];
            err = nc_put_vara_double(ncid, i, start, edge, value);
            if (!canConvert) {
                IF (err != NC_ECHAR)
                    error("expecting NC_ECHAR but got %s",nc_err_code_name(err));
                ELSE_NOK
                start[j] = 0;
                continue;
            }
            IF (err != NC_EINVALCOORDS)
                error("expecting NC_EINVALCOORDS but got %s",nc_err_code_name(err));
            ELSE_NOK
            start[j] = 0;
            edge[j] = var_shape[i][j] + 1;
            err = nc_put_vara_double(ncid, i, start, edge, value);
            IF (err != NC_EEDGE)
                error("expecting NC_EEDG but got %s",nc_err_code_name(err));
            ELSE_NOK
            edge[j] = 1;
        }

        /* Check correct error returned when nothing to put, when edge[*]==0 */
        for (j = 0; j < var_rank[i]; j++) edge[j] = 0;

        for (j = 0; j < var_rank[i]; j++) {
            if (var_dimid[i][j] == RECDIM) continue; /* skip record dim */
            start[j] = var_shape[i][j];
            err = nc_put_vara_double(ncid, i, start, edge, value);
            if (!canConvert) {
                IF (err != NC_ECHAR)
                    error("expecting NC_ECHAR but got %s",nc_err_code_name(err));
                ELSE_NOK
                start[j] = 0;
                continue;
            }
#ifdef RELAX_COORD_BOUND
            IF (err != NC_NOERR) /* allowed when edge[j]==0 */
                error("expecting NC_NOERR but got %s",nc_err_code_name(err));
#else
            IF (err != NC_EINVALCOORDS) /* not allowed even when edge[j]==0 */
                error("expecting NC_EINVALCOORDS but got %s",nc_err_code_name(err));
#endif
            ELSE_NOK
            start[j] = var_shape[i][j]+1; /* out of boundary check */
            err = nc_put_vara_double(ncid, i, start, edge, value);
            IF (err != NC_EINVALCOORDS)
                error("expecting NC_EINVALCOORDS but got %s",nc_err_code_name(err));
            ELSE_NOK
            start[j] = 0;
        }
        for (j = 0; j < var_rank[i]; j++) edge[j] = 1;

        /* Choose a random point dividing each dim into 2 parts */
        /* Put 2^rank (nslabs) slabs so defined */
        nslabs = 1;
        for (j = 0; j < var_rank[i]; j++) {
            mid[j] = roll( var_shape[i][j] );
            nslabs *= 2;
        }
        /* bits of k determine whether to put lower or upper part of dim */
        for (k = 0; k < nslabs; k++) {
            nels = 1;
            for (j = 0; j < var_rank[i]; j++) {
                if ((k >> j) & 1) {
                    start[j] = 0;
                    edge[j] = mid[j];
                } else {
                    start[j] = mid[j];
                    edge[j] = var_shape[i][j] - mid[j];
                }
                nels *= edge[j];
            }

            for (allInExtRange = 1, j = 0; j < nels; j++) {
                err = toMixedBase(j, var_rank[i], edge, index);
                IF (err != 0) error("error in toMixedBase");
                for (d = 0; d < var_rank[i]; d++)
                    index[d] += start[d];
                value[j]= hash_double(cdf_format,var_type[i], var_rank[i], index,
                                  NCT_DOUBLE);
                
                    allInExtRange &= inRange3(cdf_format, (double)value[j],
                                              var_type[i], NCT_DOUBLE);
            }
            err = nc_put_vara_double(ncid, i, start, edge, value);
            if (canConvert) {
                if (allInExtRange) {
                    IF (err != NC_NOERR)
                        error("expecting NC_NOERR but got %s",nc_err_code_name(err));
                    ELSE_NOK
                }
                
                    else {

                        IF (err != NC_ERANGE)
                            error("expecting NC_ERANGE but got %s",nc_err_code_name(err));
                        ELSE_NOK
                    }


            } else {
                IF (err != NC_ECHAR)
                    error("expecting NC_ECHAR but got %s",nc_err_code_name(err));
                ELSE_NOK
            }
        }
    }

    err =  nc_close(ncid);
    IF (err != NC_NOERR)
        error("close: %s",  nc_strerror(err));

    nok += check_vars_double(scratch, numVars);

    err = nc_delete(scratch);
    IF (err != NC_NOERR)
        error("delete file %s failed", scratch);
    return nok;
}

int
test_nc_put_vara_ushort(void)
{
    int i, k, d, err, nslabs, ncid, cdf_format, nok=0;
    int canConvert;        /* Both text or both numeric */
    int allInExtRange;     /* all values within external range? */
    size_t j, nels;
    size_t start[MAX_RANK], edge[MAX_RANK];
    size_t mid[MAX_RANK], index[MAX_RANK];
    ushort value[MAX_NELS];

    err = file_create(scratch, NC_CLOBBER, &ncid);
    IF (err != NC_NOERR) {
        error("create: %s",  nc_strerror(err));
        return nok;
    }

    err =  nc_inq_format(ncid, &cdf_format);
    IF (err != NC_NOERR)
        error("inq_format: %s",  nc_strerror(err));

    def_dims(ncid);
    def_vars(ncid);

    err =  nc_enddef(ncid);
    IF (err != NC_NOERR)
        error("enddef: %s",  nc_strerror(err));

    /* check if can detect a bad file ID */
    err = nc_put_vara_ushort(BAD_ID, 0, NULL, NULL, NULL);
    IF (err != NC_EBADID)
        error("expecting NC_EBADID but got %s",nc_err_code_name(err));
    ELSE_NOK

    /* check if can detect a bad variable ID */
    err = nc_put_vara_ushort(ncid, BAD_VARID, NULL, NULL, NULL);
    IF (err != NC_ENOTVAR)
        error("expecting NC_ENOTVAR but got %s",nc_err_code_name(err));
    ELSE_NOK

    for (i = 0; i < numVars; i++) {
        assert(var_rank[i] <= MAX_RANK);
        assert(var_nels[i] <= MAX_NELS);

        value[0] = 5; /* reset to a value within bounds */

        /* check if can detect a bad file ID */
        err = nc_put_vara_ushort(BAD_ID, i, NULL, NULL, value);
        IF (err != NC_EBADID)
            error("expecting NC_EBADID but got %s",nc_err_code_name(err));
        ELSE_NOK

        canConvert = (var_type[i] == NC_CHAR) == (NCT_USHORT == NCT_TEXT);

        for (j = 0; j < var_rank[i]; j++) {
            start[j] = 0;
            edge[j] = 1;
        }


        /* first test when edge[*] > 0 */
        for (j = 0; j < var_rank[i]; j++) {
            if (var_dimid[i][j] == RECDIM) continue; /* skip record dim */
            start[j] = var_shape[i][j];
            err = nc_put_vara_ushort(ncid, i, start, edge, value);
            if (!canConvert) {
                IF (err != NC_ECHAR)
                    error("expecting NC_ECHAR but got %s",nc_err_code_name(err));
                ELSE_NOK
                start[j] = 0;
                continue;
            }
            IF (err != NC_EINVALCOORDS)
                error("expecting NC_EINVALCOORDS but got %s",nc_err_code_name(err));
            ELSE_NOK
            start[j] = 0;
            edge[j] = var_shape[i][j] + 1;
            err = nc_put_vara_ushort(ncid, i, start, edge, value);
            IF (err != NC_EEDGE)
                error("expecting NC_EEDG but got %s",nc_err_code_name(err));
            ELSE_NOK
            edge[j] = 1;
        }

        /* Check correct error returned when nothing to put, when edge[*]==0 */
        for (j = 0; j < var_rank[i]; j++) edge[j] = 0;

        for (j = 0; j < var_rank[i]; j++) {
            if (var_dimid[i][j] == RECDIM) continue; /* skip record dim */
            start[j] = var_shape[i][j];
            err = nc_put_vara_ushort(ncid, i, start, edge, value);
            if (!canConvert) {
                IF (err != NC_ECHAR)
                    error("expecting NC_ECHAR but got %s",nc_err_code_name(err));
                ELSE_NOK
                start[j] = 0;
                continue;
            }
#ifdef RELAX_COORD_BOUND
            IF (err != NC_NOERR) /* allowed when edge[j]==0 */
                error("expecting NC_NOERR but got %s",nc_err_code_name(err));
#else
            IF (err != NC_EINVALCOORDS) /* not allowed even when edge[j]==0 */
                error("expecting NC_EINVALCOORDS but got %s",nc_err_code_name(err));
#endif
            ELSE_NOK
            start[j] = var_shape[i][j]+1; /* out of boundary check */
            err = nc_put_vara_ushort(ncid, i, start, edge, value);
            IF (err != NC_EINVALCOORDS)
                error("expecting NC_EINVALCOORDS but got %s",nc_err_code_name(err));
            ELSE_NOK
            start[j] = 0;
        }
        for (j = 0; j < var_rank[i]; j++) edge[j] = 1;

        /* Choose a random point dividing each dim into 2 parts */
        /* Put 2^rank (nslabs) slabs so defined */
        nslabs = 1;
        for (j = 0; j < var_rank[i]; j++) {
            mid[j] = roll( var_shape[i][j] );
            nslabs *= 2;
        }
        /* bits of k determine whether to put lower or upper part of dim */
        for (k = 0; k < nslabs; k++) {
            nels = 1;
            for (j = 0; j < var_rank[i]; j++) {
                if ((k >> j) & 1) {
                    start[j] = 0;
                    edge[j] = mid[j];
                } else {
                    start[j] = mid[j];
                    edge[j] = var_shape[i][j] - mid[j];
                }
                nels *= edge[j];
            }

            for (allInExtRange = 1, j = 0; j < nels; j++) {
                err = toMixedBase(j, var_rank[i], edge, index);
                IF (err != 0) error("error in toMixedBase");
                for (d = 0; d < var_rank[i]; d++)
                    index[d] += start[d];
                value[j]= hash_ushort(cdf_format,var_type[i], var_rank[i], index,
                                  NCT_USHORT);
                
                    allInExtRange &= inRange3(cdf_format, (double)value[j],
                                              var_type[i], NCT_USHORT);
            }
            err = nc_put_vara_ushort(ncid, i, start, edge, value);
            if (canConvert) {
                if (allInExtRange) {
                    IF (err != NC_NOERR)
                        error("expecting NC_NOERR but got %s",nc_err_code_name(err));
                    ELSE_NOK
                }
                
                    else {

                        IF (err != NC_ERANGE)
                            error("expecting NC_ERANGE but got %s",nc_err_code_name(err));
                        ELSE_NOK
                    }


            } else {
                IF (err != NC_ECHAR)
                    error("expecting NC_ECHAR but got %s",nc_err_code_name(err));
                ELSE_NOK
            }
        }
    }

    err =  nc_close(ncid);
    IF (err != NC_NOERR)
        error("close: %s",  nc_strerror(err));

    nok += check_vars_ushort(scratch, numVars);

    err = nc_delete(scratch);
    IF (err != NC_NOERR)
        error("delete file %s failed", scratch);
    return nok;
}

int
test_nc_put_vara_uint(void)
{
    int i, k, d, err, nslabs, ncid, cdf_format, nok=0;
    int canConvert;        /* Both text or both numeric */
    int allInExtRange;     /* all values within external range? */
    size_t j, nels;
    size_t start[MAX_RANK], edge[MAX_RANK];
    size_t mid[MAX_RANK], index[MAX_RANK];
    uint value[MAX_NELS];

    err = file_create(scratch, NC_CLOBBER, &ncid);
    IF (err != NC_NOERR) {
        error("create: %s",  nc_strerror(err));
        return nok;
    }

    err =  nc_inq_format(ncid, &cdf_format);
    IF (err != NC_NOERR)
        error("inq_format: %s",  nc_strerror(err));

    def_dims(ncid);
    def_vars(ncid);

    err =  nc_enddef(ncid);
    IF (err != NC_NOERR)
        error("enddef: %s",  nc_strerror(err));

    /* check if can detect a bad file ID */
    err = nc_put_vara_uint(BAD_ID, 0, NULL, NULL, NULL);
    IF (err != NC_EBADID)
        error("expecting NC_EBADID but got %s",nc_err_code_name(err));
    ELSE_NOK

    /* check if can detect a bad variable ID */
    err = nc_put_vara_uint(ncid, BAD_VARID, NULL, NULL, NULL);
    IF (err != NC_ENOTVAR)
        error("expecting NC_ENOTVAR but got %s",nc_err_code_name(err));
    ELSE_NOK

    for (i = 0; i < numVars; i++) {
        assert(var_rank[i] <= MAX_RANK);
        assert(var_nels[i] <= MAX_NELS);

        value[0] = 5; /* reset to a value within bounds */

        /* check if can detect a bad file ID */
        err = nc_put_vara_uint(BAD_ID, i, NULL, NULL, value);
        IF (err != NC_EBADID)
            error("expecting NC_EBADID but got %s",nc_err_code_name(err));
        ELSE_NOK

        canConvert = (var_type[i] == NC_CHAR) == (NCT_UINT == NCT_TEXT);

        for (j = 0; j < var_rank[i]; j++) {
            start[j] = 0;
            edge[j] = 1;
        }


        /* first test when edge[*] > 0 */
        for (j = 0; j < var_rank[i]; j++) {
            if (var_dimid[i][j] == RECDIM) continue; /* skip record dim */
            start[j] = var_shape[i][j];
            err = nc_put_vara_uint(ncid, i, start, edge, value);
            if (!canConvert) {
                IF (err != NC_ECHAR)
                    error("expecting NC_ECHAR but got %s",nc_err_code_name(err));
                ELSE_NOK
                start[j] = 0;
                continue;
            }
            IF (err != NC_EINVALCOORDS)
                error("expecting NC_EINVALCOORDS but got %s",nc_err_code_name(err));
            ELSE_NOK
            start[j] = 0;
            edge[j] = var_shape[i][j] + 1;
            err = nc_put_vara_uint(ncid, i, start, edge, value);
            IF (err != NC_EEDGE)
                error("expecting NC_EEDG but got %s",nc_err_code_name(err));
            ELSE_NOK
            edge[j] = 1;
        }

        /* Check correct error returned when nothing to put, when edge[*]==0 */
        for (j = 0; j < var_rank[i]; j++) edge[j] = 0;

        for (j = 0; j < var_rank[i]; j++) {
            if (var_dimid[i][j] == RECDIM) continue; /* skip record dim */
            start[j] = var_shape[i][j];
            err = nc_put_vara_uint(ncid, i, start, edge, value);
            if (!canConvert) {
                IF (err != NC_ECHAR)
                    error("expecting NC_ECHAR but got %s",nc_err_code_name(err));
                ELSE_NOK
                start[j] = 0;
                continue;
            }
#ifdef RELAX_COORD_BOUND
            IF (err != NC_NOERR) /* allowed when edge[j]==0 */
                error("expecting NC_NOERR but got %s",nc_err_code_name(err));
#else
            IF (err != NC_EINVALCOORDS) /* not allowed even when edge[j]==0 */
                error("expecting NC_EINVALCOORDS but got %s",nc_err_code_name(err));
#endif
            ELSE_NOK
            start[j] = var_shape[i][j]+1; /* out of boundary check */
            err = nc_put_vara_uint(ncid, i, start, edge, value);
            IF (err != NC_EINVALCOORDS)
                error("expecting NC_EINVALCOORDS but got %s",nc_err_code_name(err));
            ELSE_NOK
            start[j] = 0;
        }
        for (j = 0; j < var_rank[i]; j++) edge[j] = 1;

        /* Choose a random point dividing each dim into 2 parts */
        /* Put 2^rank (nslabs) slabs so defined */
        nslabs = 1;
        for (j = 0; j < var_rank[i]; j++) {
            mid[j] = roll( var_shape[i][j] );
            nslabs *= 2;
        }
        /* bits of k determine whether to put lower or upper part of dim */
        for (k = 0; k < nslabs; k++) {
            nels = 1;
            for (j = 0; j < var_rank[i]; j++) {
                if ((k >> j) & 1) {
                    start[j] = 0;
                    edge[j] = mid[j];
                } else {
                    start[j] = mid[j];
                    edge[j] = var_shape[i][j] - mid[j];
                }
                nels *= edge[j];
            }

            for (allInExtRange = 1, j = 0; j < nels; j++) {
                err = toMixedBase(j, var_rank[i], edge, index);
                IF (err != 0) error("error in toMixedBase");
                for (d = 0; d < var_rank[i]; d++)
                    index[d] += start[d];
                value[j]= hash_uint(cdf_format,var_type[i], var_rank[i], index,
                                  NCT_UINT);
                
                    allInExtRange &= inRange3(cdf_format, (double)value[j],
                                              var_type[i], NCT_UINT);
            }
            err = nc_put_vara_uint(ncid, i, start, edge, value);
            if (canConvert) {
                if (allInExtRange) {
                    IF (err != NC_NOERR)
                        error("expecting NC_NOERR but got %s",nc_err_code_name(err));
                    ELSE_NOK
                }
                
                    else {

                        IF (err != NC_ERANGE)
                            error("expecting NC_ERANGE but got %s",nc_err_code_name(err));
                        ELSE_NOK
                    }


            } else {
                IF (err != NC_ECHAR)
                    error("expecting NC_ECHAR but got %s",nc_err_code_name(err));
                ELSE_NOK
            }
        }
    }

    err =  nc_close(ncid);
    IF (err != NC_NOERR)
        error("close: %s",  nc_strerror(err));

    nok += check_vars_uint(scratch, numVars);

    err = nc_delete(scratch);
    IF (err != NC_NOERR)
        error("delete file %s failed", scratch);
    return nok;
}

int
test_nc_put_vara_longlong(void)
{
    int i, k, d, err, nslabs, ncid, cdf_format, nok=0;
    int canConvert;        /* Both text or both numeric */
    int allInExtRange;     /* all values within external range? */
    size_t j, nels;
    size_t start[MAX_RANK], edge[MAX_RANK];
    size_t mid[MAX_RANK], index[MAX_RANK];
    longlong value[MAX_NELS];

    err = file_create(scratch, NC_CLOBBER, &ncid);
    IF (err != NC_NOERR) {
        error("create: %s",  nc_strerror(err));
        return nok;
    }

    err =  nc_inq_format(ncid, &cdf_format);
    IF (err != NC_NOERR)
        error("inq_format: %s",  nc_strerror(err));

    def_dims(ncid);
    def_vars(ncid);

    err =  nc_enddef(ncid);
    IF (err != NC_NOERR)
        error("enddef: %s",  nc_strerror(err));

    /* check if can detect a bad file ID */
    err = nc_put_vara_longlong(BAD_ID, 0, NULL, NULL, NULL);
    IF (err != NC_EBADID)
        error("expecting NC_EBADID but got %s",nc_err_code_name(err));
    ELSE_NOK

    /* check if can detect a bad variable ID */
    err = nc_put_vara_longlong(ncid, BAD_VARID, NULL, NULL, NULL);
    IF (err != NC_ENOTVAR)
        error("expecting NC_ENOTVAR but got %s",nc_err_code_name(err));
    ELSE_NOK

    for (i = 0; i < numVars; i++) {
        assert(var_rank[i] <= MAX_RANK);
        assert(var_nels[i] <= MAX_NELS);

        value[0] = 5; /* reset to a value within bounds */

        /* check if can detect a bad file ID */
        err = nc_put_vara_longlong(BAD_ID, i, NULL, NULL, value);
        IF (err != NC_EBADID)
            error("expecting NC_EBADID but got %s",nc_err_code_name(err));
        ELSE_NOK

        canConvert = (var_type[i] == NC_CHAR) == (NCT_LONGLONG == NCT_TEXT);

        for (j = 0; j < var_rank[i]; j++) {
            start[j] = 0;
            edge[j] = 1;
        }


        /* first test when edge[*] > 0 */
        for (j = 0; j < var_rank[i]; j++) {
            if (var_dimid[i][j] == RECDIM) continue; /* skip record dim */
            start[j] = var_shape[i][j];
            err = nc_put_vara_longlong(ncid, i, start, edge, value);
            if (!canConvert) {
                IF (err != NC_ECHAR)
                    error("expecting NC_ECHAR but got %s",nc_err_code_name(err));
                ELSE_NOK
                start[j] = 0;
                continue;
            }
            IF (err != NC_EINVALCOORDS)
                error("expecting NC_EINVALCOORDS but got %s",nc_err_code_name(err));
            ELSE_NOK
            start[j] = 0;
            edge[j] = var_shape[i][j] + 1;
            err = nc_put_vara_longlong(ncid, i, start, edge, value);
            IF (err != NC_EEDGE)
                error("expecting NC_EEDG but got %s",nc_err_code_name(err));
            ELSE_NOK
            edge[j] = 1;
        }

        /* Check correct error returned when nothing to put, when edge[*]==0 */
        for (j = 0; j < var_rank[i]; j++) edge[j] = 0;

        for (j = 0; j < var_rank[i]; j++) {
            if (var_dimid[i][j] == RECDIM) continue; /* skip record dim */
            start[j] = var_shape[i][j];
            err = nc_put_vara_longlong(ncid, i, start, edge, value);
            if (!canConvert) {
                IF (err != NC_ECHAR)
                    error("expecting NC_ECHAR but got %s",nc_err_code_name(err));
                ELSE_NOK
                start[j] = 0;
                continue;
            }
#ifdef RELAX_COORD_BOUND
            IF (err != NC_NOERR) /* allowed when edge[j]==0 */
                error("expecting NC_NOERR but got %s",nc_err_code_name(err));
#else
            IF (err != NC_EINVALCOORDS) /* not allowed even when edge[j]==0 */
                error("expecting NC_EINVALCOORDS but got %s",nc_err_code_name(err));
#endif
            ELSE_NOK
            start[j] = var_shape[i][j]+1; /* out of boundary check */
            err = nc_put_vara_longlong(ncid, i, start, edge, value);
            IF (err != NC_EINVALCOORDS)
                error("expecting NC_EINVALCOORDS but got %s",nc_err_code_name(err));
            ELSE_NOK
            start[j] = 0;
        }
        for (j = 0; j < var_rank[i]; j++) edge[j] = 1;

        /* Choose a random point dividing each dim into 2 parts */
        /* Put 2^rank (nslabs) slabs so defined */
        nslabs = 1;
        for (j = 0; j < var_rank[i]; j++) {
            mid[j] = roll( var_shape[i][j] );
            nslabs *= 2;
        }
        /* bits of k determine whether to put lower or upper part of dim */
        for (k = 0; k < nslabs; k++) {
            nels = 1;
            for (j = 0; j < var_rank[i]; j++) {
                if ((k >> j) & 1) {
                    start[j] = 0;
                    edge[j] = mid[j];
                } else {
                    start[j] = mid[j];
                    edge[j] = var_shape[i][j] - mid[j];
                }
                nels *= edge[j];
            }

            for (allInExtRange = 1, j = 0; j < nels; j++) {
                err = toMixedBase(j, var_rank[i], edge, index);
                IF (err != 0) error("error in toMixedBase");
                for (d = 0; d < var_rank[i]; d++)
                    index[d] += start[d];
                value[j]= hash_longlong(cdf_format,var_type[i], var_rank[i], index,
                                  NCT_LONGLONG);
                
                    allInExtRange &= inRange3(cdf_format, (double)value[j],
                                              var_type[i], NCT_LONGLONG);
            }
            err = nc_put_vara_longlong(ncid, i, start, edge, value);
            if (canConvert) {
                if (allInExtRange) {
                    IF (err != NC_NOERR)
                        error("expecting NC_NOERR but got %s",nc_err_code_name(err));
                    ELSE_NOK
                }
                
                    else {

                        IF (err != NC_ERANGE)
                            error("expecting NC_ERANGE but got %s",nc_err_code_name(err));
                        ELSE_NOK
                    }


            } else {
                IF (err != NC_ECHAR)
                    error("expecting NC_ECHAR but got %s",nc_err_code_name(err));
                ELSE_NOK
            }
        }
    }

    err =  nc_close(ncid);
    IF (err != NC_NOERR)
        error("close: %s",  nc_strerror(err));

    nok += check_vars_longlong(scratch, numVars);

    err = nc_delete(scratch);
    IF (err != NC_NOERR)
        error("delete file %s failed", scratch);
    return nok;
}

int
test_nc_put_vara_ulonglong(void)
{
    int i, k, d, err, nslabs, ncid, cdf_format, nok=0;
    int canConvert;        /* Both text or both numeric */
    int allInExtRange;     /* all values within external range? */
    size_t j, nels;
    size_t start[MAX_RANK], edge[MAX_RANK];
    size_t mid[MAX_RANK], index[MAX_RANK];
    ulonglong value[MAX_NELS];

    err = file_create(scratch, NC_CLOBBER, &ncid);
    IF (err != NC_NOERR) {
        error("create: %s",  nc_strerror(err));
        return nok;
    }

    err =  nc_inq_format(ncid, &cdf_format);
    IF (err != NC_NOERR)
        error("inq_format: %s",  nc_strerror(err));

    def_dims(ncid);
    def_vars(ncid);

    err =  nc_enddef(ncid);
    IF (err != NC_NOERR)
        error("enddef: %s",  nc_strerror(err));

    /* check if can detect a bad file ID */
    err = nc_put_vara_ulonglong(BAD_ID, 0, NULL, NULL, NULL);
    IF (err != NC_EBADID)
        error("expecting NC_EBADID but got %s",nc_err_code_name(err));
    ELSE_NOK

    /* check if can detect a bad variable ID */
    err = nc_put_vara_ulonglong(ncid, BAD_VARID, NULL, NULL, NULL);
    IF (err != NC_ENOTVAR)
        error("expecting NC_ENOTVAR but got %s",nc_err_code_name(err));
    ELSE_NOK

    for (i = 0; i < numVars; i++) {
        assert(var_rank[i] <= MAX_RANK);
        assert(var_nels[i] <= MAX_NELS);

        value[0] = 5; /* reset to a value within bounds */

        /* check if can detect a bad file ID */
        err = nc_put_vara_ulonglong(BAD_ID, i, NULL, NULL, value);
        IF (err != NC_EBADID)
            error("expecting NC_EBADID but got %s",nc_err_code_name(err));
        ELSE_NOK

        canConvert = (var_type[i] == NC_CHAR) == (NCT_ULONGLONG == NCT_TEXT);

        for (j = 0; j < var_rank[i]; j++) {
            start[j] = 0;
            edge[j] = 1;
        }


        /* first test when edge[*] > 0 */
        for (j = 0; j < var_rank[i]; j++) {
            if (var_dimid[i][j] == RECDIM) continue; /* skip record dim */
            start[j] = var_shape[i][j];
            err = nc_put_vara_ulonglong(ncid, i, start, edge, value);
            if (!canConvert) {
                IF (err != NC_ECHAR)
                    error("expecting NC_ECHAR but got %s",nc_err_code_name(err));
                ELSE_NOK
                start[j] = 0;
                continue;
            }
            IF (err != NC_EINVALCOORDS)
                error("expecting NC_EINVALCOORDS but got %s",nc_err_code_name(err));
            ELSE_NOK
            start[j] = 0;
            edge[j] = var_shape[i][j] + 1;
            err = nc_put_vara_ulonglong(ncid, i, start, edge, value);
            IF (err != NC_EEDGE)
                error("expecting NC_EEDG but got %s",nc_err_code_name(err));
            ELSE_NOK
            edge[j] = 1;
        }

        /* Check correct error returned when nothing to put, when edge[*]==0 */
        for (j = 0; j < var_rank[i]; j++) edge[j] = 0;

        for (j = 0; j < var_rank[i]; j++) {
            if (var_dimid[i][j] == RECDIM) continue; /* skip record dim */
            start[j] = var_shape[i][j];
            err = nc_put_vara_ulonglong(ncid, i, start, edge, value);
            if (!canConvert) {
                IF (err != NC_ECHAR)
                    error("expecting NC_ECHAR but got %s",nc_err_code_name(err));
                ELSE_NOK
                start[j] = 0;
                continue;
            }
#ifdef RELAX_COORD_BOUND
            IF (err != NC_NOERR) /* allowed when edge[j]==0 */
                error("expecting NC_NOERR but got %s",nc_err_code_name(err));
#else
            IF (err != NC_EINVALCOORDS) /* not allowed even when edge[j]==0 */
                error("expecting NC_EINVALCOORDS but got %s",nc_err_code_name(err));
#endif
            ELSE_NOK
            start[j] = var_shape[i][j]+1; /* out of boundary check */
            err = nc_put_vara_ulonglong(ncid, i, start, edge, value);
            IF (err != NC_EINVALCOORDS)
                error("expecting NC_EINVALCOORDS but got %s",nc_err_code_name(err));
            ELSE_NOK
            start[j] = 0;
        }
        for (j = 0; j < var_rank[i]; j++) edge[j] = 1;

        /* Choose a random point dividing each dim into 2 parts */
        /* Put 2^rank (nslabs) slabs so defined */
        nslabs = 1;
        for (j = 0; j < var_rank[i]; j++) {
            mid[j] = roll( var_shape[i][j] );
            nslabs *= 2;
        }
        /* bits of k determine whether to put lower or upper part of dim */
        for (k = 0; k < nslabs; k++) {
            nels = 1;
            for (j = 0; j < var_rank[i]; j++) {
                if ((k >> j) & 1) {
                    start[j] = 0;
                    edge[j] = mid[j];
                } else {
                    start[j] = mid[j];
                    edge[j] = var_shape[i][j] - mid[j];
                }
                nels *= edge[j];
            }

            for (allInExtRange = 1, j = 0; j < nels; j++) {
                err = toMixedBase(j, var_rank[i], edge, index);
                IF (err != 0) error("error in toMixedBase");
                for (d = 0; d < var_rank[i]; d++)
                    index[d] += start[d];
                value[j]= hash_ulonglong(cdf_format,var_type[i], var_rank[i], index,
                                  NCT_ULONGLONG);
                
                    allInExtRange &= inRange3(cdf_format, (double)value[j],
                                              var_type[i], NCT_ULONGLONG);
            }
            err = nc_put_vara_ulonglong(ncid, i, start, edge, value);
            if (canConvert) {
                if (allInExtRange) {
                    IF (err != NC_NOERR)
                        error("expecting NC_NOERR but got %s",nc_err_code_name(err));
                    ELSE_NOK
                }
                
                    else {

                        IF (err != NC_ERANGE)
                            error("expecting NC_ERANGE but got %s",nc_err_code_name(err));
                        ELSE_NOK
                    }


            } else {
                IF (err != NC_ECHAR)
                    error("expecting NC_ECHAR but got %s",nc_err_code_name(err));
                ELSE_NOK
            }
        }
    }

    err =  nc_close(ncid);
    IF (err != NC_NOERR)
        error("close: %s",  nc_strerror(err));

    nok += check_vars_ulonglong(scratch, numVars);

    err = nc_delete(scratch);
    IF (err != NC_NOERR)
        error("delete file %s failed", scratch);
    return nok;
}




int
test_nc_put_vars_text(void)
{
    int i, k, d, err, nslabs, ncid, cdf_format, nok=0;
    int canConvert;     /* Both text or both numeric */
    int allInExtRange;  /* all values within external range? */
    size_t j, m, nels;
    size_t start[MAX_RANK], edge[MAX_RANK], index[MAX_RANK];
    size_t index2[MAX_RANK], mid[MAX_RANK], count[MAX_RANK];
    size_t sstride[MAX_RANK];
    ptrdiff_t nstarts;   /* number of different starts */
    ptrdiff_t stride[MAX_RANK];
    text value[MAX_NELS];

    err = file_create(scratch, NC_CLOBBER, &ncid);
    IF (err != NC_NOERR) {
        error("create: %s",  nc_strerror(err));
        return nok;
    }

    err =  nc_inq_format(ncid, &cdf_format);
    IF (err != NC_NOERR)
        error("inq_format: %s",  nc_strerror(err));

    def_dims(ncid);
    def_vars(ncid);

    err =  nc_enddef(ncid);
    IF (err != NC_NOERR)
        error("enddef: %s",  nc_strerror(err));

    /* check if can detect a bad file ID */
    err = nc_put_vars_text(BAD_ID, 0, NULL, NULL, NULL, NULL);
    IF (err != NC_EBADID)
        error("expecting NC_EBADID but got %s",nc_err_code_name(err));
    ELSE_NOK

    /* check if can detect a bad variable ID */
    err = nc_put_vars_text(ncid, BAD_VARID, NULL, NULL, NULL, NULL);
    IF (err != NC_ENOTVAR)
        error("expecting NC_ENOTVAR but got %s",nc_err_code_name(err));
    ELSE_NOK

    for (i = 0; i < numVars; i++) {
        assert(var_rank[i] <= MAX_RANK);
        assert(var_nels[i] <= MAX_NELS);

        value[0] = 5; /* reset to a value within bounds */

        /* check if can detect a bad file ID */
        err = nc_put_vars_text(BAD_ID, i, NULL, NULL, NULL, value);
        IF (err != NC_EBADID)
            error("expecting NC_EBADID but got %s",nc_err_code_name(err));
        ELSE_NOK

        canConvert = (var_type[i] == NC_CHAR) ;

        for (j = 0; j < var_rank[i]; j++) {
            start[j] = 0;
            edge[j] = 1;
            stride[j] = 1;
        }

        /* first test when edge[*] > 0 */
        for (j = 0; j < var_rank[i]; j++) {
            if (var_dimid[i][j] == RECDIM) continue; /* skip record dim */
            start[j] = var_shape[i][j];   /* out of boundary check */
            err = nc_put_vars_text(ncid, i, start, edge, stride, value);
            if (!canConvert) {
                IF (err != NC_ECHAR)
                    error("expecting NC_ECHAR but got %s",nc_err_code_name(err));
                ELSE_NOK
                start[j] = 0;
                continue;
            }
            IF (err != NC_EINVALCOORDS)
                error("expecting NC_EINVALCOORDS but got %s",nc_err_code_name(err));
            ELSE_NOK
            start[j] = 0;
            edge[j] = var_shape[i][j] + 1;
            err = nc_put_vars_text(ncid, i, start, edge, stride, value);
            IF (err != NC_EEDGE)
                error("expecting NC_EEDGE but got %s",nc_err_code_name(err));
            ELSE_NOK
            edge[j] = 1;
            stride[j] = 0;
            err = nc_put_vars_text(ncid, i, start, edge, stride, value);
            IF (err != NC_ESTRIDE)
                error("expecting NC_ESTRIDE but got %s",nc_err_code_name(err));
            ELSE_NOK
            stride[j] = 1;
        }
        /* Check correct error returned even when nothing to put */
        for (j = 0; j < var_rank[i]; j++) edge[j] = 0;

        for (j = 0; j < var_rank[i]; j++) {
            if (var_dimid[i][j] == RECDIM) continue; /* skip record dim */
            start[j] = var_shape[i][j];
            err = nc_put_vars_text(ncid, i, start, edge, stride, value);
            if (!canConvert) {
                IF (err != NC_ECHAR)
                    error("expecting NC_ECHAR but got %s",nc_err_code_name(err));
                ELSE_NOK
                start[j] = 0;
                continue;
            }
#ifdef RELAX_COORD_BOUND
            IF (err != NC_NOERR) /* allowed when edge[j]==0 */
                error("expecting NC_NOERR but got %s",nc_err_code_name(err));
#else
            IF (err != NC_EINVALCOORDS) /* not allowed even when edge[j]==0 */
                error("expecting NC_EINVALCOORDS but got %s",nc_err_code_name(err));
#endif
            ELSE_NOK
            start[j] = var_shape[i][j]+1; /* out of boundary check */
            err = nc_put_vars_text(ncid, i, start, edge, stride, value);
            IF (err != NC_EINVALCOORDS)
                error("expecting NC_EINVALCOORDS but got %s",nc_err_code_name(err));
            ELSE_NOK
            start[j] = 0;
        }
        for (j = 0; j < var_rank[i]; j++) edge[j] = 1;

        /* Choose a random point dividing each dim into 2 parts */
        /* Put 2^rank (nslabs) slabs so defined */
        nslabs = 1;
        for (j = 0; j < var_rank[i]; j++) {
            mid[j] = roll( var_shape[i][j] );
            nslabs *= 2;
        }
        /* bits of k determine whether to put lower or upper part of dim */
        /* choose random stride from 1 to edge */
        for (k = 0; k < nslabs; k++) {
            nstarts = 1;
            for (j = 0; j < var_rank[i]; j++) {
                if ((k >> j) & 1) {
                    start[j] = 0;
                    edge[j] = mid[j];
                } else {
                    start[j] = mid[j];
                    edge[j] = var_shape[i][j] - mid[j];
                }
                sstride[j] = edge[j] > 0 ? 1+roll(edge[j]) : 1;
                stride[j] = (ptrdiff_t)sstride[j];
                nstarts *= stride[j];
            }
            for (m = 0; m < nstarts; m++) {
                err = toMixedBase(m, var_rank[i], sstride, index);
                IF (err != 0) error("error in toMixedBase");
                nels = 1;
                for (j = 0; j < var_rank[i]; j++) {
                    count[j] = 1 + (edge[j] - index[j] - 1) / (size_t)stride[j];
                    nels *= count[j];
                    index[j] += start[j];
                }
                /* Random choice of forward or backward */
/* TODO
                if ( roll(2) ) {
                    for (j = 0; j < var_rank[i]; j++) {
                        index[j] += (count[j] - 1) * (size_t)stride[j];
                        stride[j] = -stride[j];
                    }
                }
*/
                for (allInExtRange = 1, j = 0; j < nels; j++) {
                    err = toMixedBase(j, var_rank[i], count, index2);
                    IF (err != 0) error("error in toMixedBase");
                    for (d = 0; d < var_rank[i]; d++)
                        index2[d] = index[d] + index2[d] * (size_t)stride[d];
                    value[j] = hash_text(cdf_format,var_type[i], var_rank[i],
                                       index2, NCT_TEXT);
                    if (var_type[i] != NC_CHAR)
                        allInExtRange &= inRange3(cdf_format, (double)value[j],
                                                  var_type[i], NCT_TEXT);
                }
                err = nc_put_vars_text(ncid, i, index, count, stride, value);
                if (canConvert) {
                    if (allInExtRange) {
                        IF (err != NC_NOERR)
                            error("expecting NC_NOERR but got %s",nc_err_code_name(err));
                        ELSE_NOK
                    }
                    
                    else {

                        IF (err != NC_ERANGE)
                            error("expecting NC_ERANGE but got %s",nc_err_code_name(err));
                        ELSE_NOK
                    }


                } else {
                    IF (err != NC_ECHAR)
                        error("expecting NC_ECHAR but got %s",nc_err_code_name(err));
                    ELSE_NOK
                }
            }
        }
    }

    err =  nc_close(ncid);
    IF (err != NC_NOERR)
        error("close: %s",  nc_strerror(err));

    nok += check_vars_text(scratch, numVars);

    err = nc_delete(scratch);
    IF (err != NC_NOERR)
        error("delete file %s failed", scratch);
    return nok;
}

int
test_nc_put_vars_uchar(void)
{
    int i, k, d, err, nslabs, ncid, cdf_format, nok=0;
    int canConvert;     /* Both text or both numeric */
    int allInExtRange;  /* all values within external range? */
    size_t j, m, nels;
    size_t start[MAX_RANK], edge[MAX_RANK], index[MAX_RANK];
    size_t index2[MAX_RANK], mid[MAX_RANK], count[MAX_RANK];
    size_t sstride[MAX_RANK];
    ptrdiff_t nstarts;   /* number of different starts */
    ptrdiff_t stride[MAX_RANK];
    uchar value[MAX_NELS];

    err = file_create(scratch, NC_CLOBBER, &ncid);
    IF (err != NC_NOERR) {
        error("create: %s",  nc_strerror(err));
        return nok;
    }

    err =  nc_inq_format(ncid, &cdf_format);
    IF (err != NC_NOERR)
        error("inq_format: %s",  nc_strerror(err));

    def_dims(ncid);
    def_vars(ncid);

    err =  nc_enddef(ncid);
    IF (err != NC_NOERR)
        error("enddef: %s",  nc_strerror(err));

    /* check if can detect a bad file ID */
    err = nc_put_vars_uchar(BAD_ID, 0, NULL, NULL, NULL, NULL);
    IF (err != NC_EBADID)
        error("expecting NC_EBADID but got %s",nc_err_code_name(err));
    ELSE_NOK

    /* check if can detect a bad variable ID */
    err = nc_put_vars_uchar(ncid, BAD_VARID, NULL, NULL, NULL, NULL);
    IF (err != NC_ENOTVAR)
        error("expecting NC_ENOTVAR but got %s",nc_err_code_name(err));
    ELSE_NOK

    for (i = 0; i < numVars; i++) {
        assert(var_rank[i] <= MAX_RANK);
        assert(var_nels[i] <= MAX_NELS);

        value[0] = 5; /* reset to a value within bounds */

        /* check if can detect a bad file ID */
        err = nc_put_vars_uchar(BAD_ID, i, NULL, NULL, NULL, value);
        IF (err != NC_EBADID)
            error("expecting NC_EBADID but got %s",nc_err_code_name(err));
        ELSE_NOK

        canConvert = (var_type[i] == NC_CHAR) == (NCT_UCHAR == NCT_TEXT);

        for (j = 0; j < var_rank[i]; j++) {
            start[j] = 0;
            edge[j] = 1;
            stride[j] = 1;
        }

        /* first test when edge[*] > 0 */
        for (j = 0; j < var_rank[i]; j++) {
            if (var_dimid[i][j] == RECDIM) continue; /* skip record dim */
            start[j] = var_shape[i][j];   /* out of boundary check */
            err = nc_put_vars_uchar(ncid, i, start, edge, stride, value);
            if (!canConvert) {
                IF (err != NC_ECHAR)
                    error("expecting NC_ECHAR but got %s",nc_err_code_name(err));
                ELSE_NOK
                start[j] = 0;
                continue;
            }
            IF (err != NC_EINVALCOORDS)
                error("expecting NC_EINVALCOORDS but got %s",nc_err_code_name(err));
            ELSE_NOK
            start[j] = 0;
            edge[j] = var_shape[i][j] + 1;
            err = nc_put_vars_uchar(ncid, i, start, edge, stride, value);
            IF (err != NC_EEDGE)
                error("expecting NC_EEDGE but got %s",nc_err_code_name(err));
            ELSE_NOK
            edge[j] = 1;
            stride[j] = 0;
            err = nc_put_vars_uchar(ncid, i, start, edge, stride, value);
            IF (err != NC_ESTRIDE)
                error("expecting NC_ESTRIDE but got %s",nc_err_code_name(err));
            ELSE_NOK
            stride[j] = 1;
        }
        /* Check correct error returned even when nothing to put */
        for (j = 0; j < var_rank[i]; j++) edge[j] = 0;

        for (j = 0; j < var_rank[i]; j++) {
            if (var_dimid[i][j] == RECDIM) continue; /* skip record dim */
            start[j] = var_shape[i][j];
            err = nc_put_vars_uchar(ncid, i, start, edge, stride, value);
            if (!canConvert) {
                IF (err != NC_ECHAR)
                    error("expecting NC_ECHAR but got %s",nc_err_code_name(err));
                ELSE_NOK
                start[j] = 0;
                continue;
            }
#ifdef RELAX_COORD_BOUND
            IF (err != NC_NOERR) /* allowed when edge[j]==0 */
                error("expecting NC_NOERR but got %s",nc_err_code_name(err));
#else
            IF (err != NC_EINVALCOORDS) /* not allowed even when edge[j]==0 */
                error("expecting NC_EINVALCOORDS but got %s",nc_err_code_name(err));
#endif
            ELSE_NOK
            start[j] = var_shape[i][j]+1; /* out of boundary check */
            err = nc_put_vars_uchar(ncid, i, start, edge, stride, value);
            IF (err != NC_EINVALCOORDS)
                error("expecting NC_EINVALCOORDS but got %s",nc_err_code_name(err));
            ELSE_NOK
            start[j] = 0;
        }
        for (j = 0; j < var_rank[i]; j++) edge[j] = 1;

        /* Choose a random point dividing each dim into 2 parts */
        /* Put 2^rank (nslabs) slabs so defined */
        nslabs = 1;
        for (j = 0; j < var_rank[i]; j++) {
            mid[j] = roll( var_shape[i][j] );
            nslabs *= 2;
        }
        /* bits of k determine whether to put lower or upper part of dim */
        /* choose random stride from 1 to edge */
        for (k = 0; k < nslabs; k++) {
            nstarts = 1;
            for (j = 0; j < var_rank[i]; j++) {
                if ((k >> j) & 1) {
                    start[j] = 0;
                    edge[j] = mid[j];
                } else {
                    start[j] = mid[j];
                    edge[j] = var_shape[i][j] - mid[j];
                }
                sstride[j] = edge[j] > 0 ? 1+roll(edge[j]) : 1;
                stride[j] = (ptrdiff_t)sstride[j];
                nstarts *= stride[j];
            }
            for (m = 0; m < nstarts; m++) {
                err = toMixedBase(m, var_rank[i], sstride, index);
                IF (err != 0) error("error in toMixedBase");
                nels = 1;
                for (j = 0; j < var_rank[i]; j++) {
                    count[j] = 1 + (edge[j] - index[j] - 1) / (size_t)stride[j];
                    nels *= count[j];
                    index[j] += start[j];
                }
                /* Random choice of forward or backward */
/* TODO
                if ( roll(2) ) {
                    for (j = 0; j < var_rank[i]; j++) {
                        index[j] += (count[j] - 1) * (size_t)stride[j];
                        stride[j] = -stride[j];
                    }
                }
*/
                for (allInExtRange = 1, j = 0; j < nels; j++) {
                    err = toMixedBase(j, var_rank[i], count, index2);
                    IF (err != 0) error("error in toMixedBase");
                    for (d = 0; d < var_rank[i]; d++)
                        index2[d] = index[d] + index2[d] * (size_t)stride[d];
                    value[j] = hash_uchar(cdf_format,var_type[i], var_rank[i],
                                       index2, NCT_UCHAR);
                    
                        allInExtRange &= inRange3(cdf_format, (double)value[j],
                                                  var_type[i], NCT_UCHAR);
                }
                err = nc_put_vars_uchar(ncid, i, index, count, stride, value);
                if (canConvert) {
                    if (allInExtRange) {
                        IF (err != NC_NOERR)
                            error("expecting NC_NOERR but got %s",nc_err_code_name(err));
                        ELSE_NOK
                    }
                    
#if !defined(USE_PNETCDF) || (PNETCDF_VERSION_MAJOR==1 && PNETCDF_VERSION_MINOR>=8)
                    else {

                        IF (err != NC_ERANGE)
                            error("expecting NC_ERANGE but got %s",nc_err_code_name(err));
                        ELSE_NOK
                    }
#endif

                } else {
                    IF (err != NC_ECHAR)
                        error("expecting NC_ECHAR but got %s",nc_err_code_name(err));
                    ELSE_NOK
                }
            }
        }
    }

    err =  nc_close(ncid);
    IF (err != NC_NOERR)
        error("close: %s",  nc_strerror(err));

    nok += check_vars_uchar(scratch, numVars);

    err = nc_delete(scratch);
    IF (err != NC_NOERR)
        error("delete file %s failed", scratch);
    return nok;
}

int
test_nc_put_vars_schar(void)
{
    int i, k, d, err, nslabs, ncid, cdf_format, nok=0;
    int canConvert;     /* Both text or both numeric */
    int allInExtRange;  /* all values within external range? */
    size_t j, m, nels;
    size_t start[MAX_RANK], edge[MAX_RANK], index[MAX_RANK];
    size_t index2[MAX_RANK], mid[MAX_RANK], count[MAX_RANK];
    size_t sstride[MAX_RANK];
    ptrdiff_t nstarts;   /* number of different starts */
    ptrdiff_t stride[MAX_RANK];
    schar value[MAX_NELS];

    err = file_create(scratch, NC_CLOBBER, &ncid);
    IF (err != NC_NOERR) {
        error("create: %s",  nc_strerror(err));
        return nok;
    }

    err =  nc_inq_format(ncid, &cdf_format);
    IF (err != NC_NOERR)
        error("inq_format: %s",  nc_strerror(err));

    def_dims(ncid);
    def_vars(ncid);

    err =  nc_enddef(ncid);
    IF (err != NC_NOERR)
        error("enddef: %s",  nc_strerror(err));

    /* check if can detect a bad file ID */
    err = nc_put_vars_schar(BAD_ID, 0, NULL, NULL, NULL, NULL);
    IF (err != NC_EBADID)
        error("expecting NC_EBADID but got %s",nc_err_code_name(err));
    ELSE_NOK

    /* check if can detect a bad variable ID */
    err = nc_put_vars_schar(ncid, BAD_VARID, NULL, NULL, NULL, NULL);
    IF (err != NC_ENOTVAR)
        error("expecting NC_ENOTVAR but got %s",nc_err_code_name(err));
    ELSE_NOK

    for (i = 0; i < numVars; i++) {
        assert(var_rank[i] <= MAX_RANK);
        assert(var_nels[i] <= MAX_NELS);

        value[0] = 5; /* reset to a value within bounds */

        /* check if can detect a bad file ID */
        err = nc_put_vars_schar(BAD_ID, i, NULL, NULL, NULL, value);
        IF (err != NC_EBADID)
            error("expecting NC_EBADID but got %s",nc_err_code_name(err));
        ELSE_NOK

        canConvert = (var_type[i] == NC_CHAR) == (NCT_SCHAR == NCT_TEXT);

        for (j = 0; j < var_rank[i]; j++) {
            start[j] = 0;
            edge[j] = 1;
            stride[j] = 1;
        }

        /* first test when edge[*] > 0 */
        for (j = 0; j < var_rank[i]; j++) {
            if (var_dimid[i][j] == RECDIM) continue; /* skip record dim */
            start[j] = var_shape[i][j];   /* out of boundary check */
            err = nc_put_vars_schar(ncid, i, start, edge, stride, value);
            if (!canConvert) {
                IF (err != NC_ECHAR)
                    error("expecting NC_ECHAR but got %s",nc_err_code_name(err));
                ELSE_NOK
                start[j] = 0;
                continue;
            }
            IF (err != NC_EINVALCOORDS)
                error("expecting NC_EINVALCOORDS but got %s",nc_err_code_name(err));
            ELSE_NOK
            start[j] = 0;
            edge[j] = var_shape[i][j] + 1;
            err = nc_put_vars_schar(ncid, i, start, edge, stride, value);
            IF (err != NC_EEDGE)
                error("expecting NC_EEDGE but got %s",nc_err_code_name(err));
            ELSE_NOK
            edge[j] = 1;
            stride[j] = 0;
            err = nc_put_vars_schar(ncid, i, start, edge, stride, value);
            IF (err != NC_ESTRIDE)
                error("expecting NC_ESTRIDE but got %s",nc_err_code_name(err));
            ELSE_NOK
            stride[j] = 1;
        }
        /* Check correct error returned even when nothing to put */
        for (j = 0; j < var_rank[i]; j++) edge[j] = 0;

        for (j = 0; j < var_rank[i]; j++) {
            if (var_dimid[i][j] == RECDIM) continue; /* skip record dim */
            start[j] = var_shape[i][j];
            err = nc_put_vars_schar(ncid, i, start, edge, stride, value);
            if (!canConvert) {
                IF (err != NC_ECHAR)
                    error("expecting NC_ECHAR but got %s",nc_err_code_name(err));
                ELSE_NOK
                start[j] = 0;
                continue;
            }
#ifdef RELAX_COORD_BOUND
            IF (err != NC_NOERR) /* allowed when edge[j]==0 */
                error("expecting NC_NOERR but got %s",nc_err_code_name(err));
#else
            IF (err != NC_EINVALCOORDS) /* not allowed even when edge[j]==0 */
                error("expecting NC_EINVALCOORDS but got %s",nc_err_code_name(err));
#endif
            ELSE_NOK
            start[j] = var_shape[i][j]+1; /* out of boundary check */
            err = nc_put_vars_schar(ncid, i, start, edge, stride, value);
            IF (err != NC_EINVALCOORDS)
                error("expecting NC_EINVALCOORDS but got %s",nc_err_code_name(err));
            ELSE_NOK
            start[j] = 0;
        }
        for (j = 0; j < var_rank[i]; j++) edge[j] = 1;

        /* Choose a random point dividing each dim into 2 parts */
        /* Put 2^rank (nslabs) slabs so defined */
        nslabs = 1;
        for (j = 0; j < var_rank[i]; j++) {
            mid[j] = roll( var_shape[i][j] );
            nslabs *= 2;
        }
        /* bits of k determine whether to put lower or upper part of dim */
        /* choose random stride from 1 to edge */
        for (k = 0; k < nslabs; k++) {
            nstarts = 1;
            for (j = 0; j < var_rank[i]; j++) {
                if ((k >> j) & 1) {
                    start[j] = 0;
                    edge[j] = mid[j];
                } else {
                    start[j] = mid[j];
                    edge[j] = var_shape[i][j] - mid[j];
                }
                sstride[j] = edge[j] > 0 ? 1+roll(edge[j]) : 1;
                stride[j] = (ptrdiff_t)sstride[j];
                nstarts *= stride[j];
            }
            for (m = 0; m < nstarts; m++) {
                err = toMixedBase(m, var_rank[i], sstride, index);
                IF (err != 0) error("error in toMixedBase");
                nels = 1;
                for (j = 0; j < var_rank[i]; j++) {
                    count[j] = 1 + (edge[j] - index[j] - 1) / (size_t)stride[j];
                    nels *= count[j];
                    index[j] += start[j];
                }
                /* Random choice of forward or backward */
/* TODO
                if ( roll(2) ) {
                    for (j = 0; j < var_rank[i]; j++) {
                        index[j] += (count[j] - 1) * (size_t)stride[j];
                        stride[j] = -stride[j];
                    }
                }
*/
                for (allInExtRange = 1, j = 0; j < nels; j++) {
                    err = toMixedBase(j, var_rank[i], count, index2);
                    IF (err != 0) error("error in toMixedBase");
                    for (d = 0; d < var_rank[i]; d++)
                        index2[d] = index[d] + index2[d] * (size_t)stride[d];
                    value[j] = hash_schar(cdf_format,var_type[i], var_rank[i],
                                       index2, NCT_SCHAR);
                    
                        allInExtRange &= inRange3(cdf_format, (double)value[j],
                                                  var_type[i], NCT_SCHAR);
                }
                err = nc_put_vars_schar(ncid, i, index, count, stride, value);
                if (canConvert) {
                    if (allInExtRange) {
                        IF (err != NC_NOERR)
                            error("expecting NC_NOERR but got %s",nc_err_code_name(err));
                        ELSE_NOK
                    }
                    
#if defined(USE_PNETCDF) && PNETCDF_VERSION_MAJOR==1 && PNETCDF_VERSION_MINOR<7
                    else if (cdf_format < NC_FORMAT_CDF5) {
#else
                    else {
#endif
                        IF (err != NC_ERANGE)
                            error("expecting NC_ERANGE but got %s",nc_err_code_name(err));
                        ELSE_NOK
                    }


                } else {
                    IF (err != NC_ECHAR)
                        error("expecting NC_ECHAR but got %s",nc_err_code_name(err));
                    ELSE_NOK
                }
            }
        }
    }

    err =  nc_close(ncid);
    IF (err != NC_NOERR)
        error("close: %s",  nc_strerror(err));

    nok += check_vars_schar(scratch, numVars);

    err = nc_delete(scratch);
    IF (err != NC_NOERR)
        error("delete file %s failed", scratch);
    return nok;
}

int
test_nc_put_vars_short(void)
{
    int i, k, d, err, nslabs, ncid, cdf_format, nok=0;
    int canConvert;     /* Both text or both numeric */
    int allInExtRange;  /* all values within external range? */
    size_t j, m, nels;
    size_t start[MAX_RANK], edge[MAX_RANK], index[MAX_RANK];
    size_t index2[MAX_RANK], mid[MAX_RANK], count[MAX_RANK];
    size_t sstride[MAX_RANK];
    ptrdiff_t nstarts;   /* number of different starts */
    ptrdiff_t stride[MAX_RANK];
    short value[MAX_NELS];

    err = file_create(scratch, NC_CLOBBER, &ncid);
    IF (err != NC_NOERR) {
        error("create: %s",  nc_strerror(err));
        return nok;
    }

    err =  nc_inq_format(ncid, &cdf_format);
    IF (err != NC_NOERR)
        error("inq_format: %s",  nc_strerror(err));

    def_dims(ncid);
    def_vars(ncid);

    err =  nc_enddef(ncid);
    IF (err != NC_NOERR)
        error("enddef: %s",  nc_strerror(err));

    /* check if can detect a bad file ID */
    err = nc_put_vars_short(BAD_ID, 0, NULL, NULL, NULL, NULL);
    IF (err != NC_EBADID)
        error("expecting NC_EBADID but got %s",nc_err_code_name(err));
    ELSE_NOK

    /* check if can detect a bad variable ID */
    err = nc_put_vars_short(ncid, BAD_VARID, NULL, NULL, NULL, NULL);
    IF (err != NC_ENOTVAR)
        error("expecting NC_ENOTVAR but got %s",nc_err_code_name(err));
    ELSE_NOK

    for (i = 0; i < numVars; i++) {
        assert(var_rank[i] <= MAX_RANK);
        assert(var_nels[i] <= MAX_NELS);

        value[0] = 5; /* reset to a value within bounds */

        /* check if can detect a bad file ID */
        err = nc_put_vars_short(BAD_ID, i, NULL, NULL, NULL, value);
        IF (err != NC_EBADID)
            error("expecting NC_EBADID but got %s",nc_err_code_name(err));
        ELSE_NOK

        canConvert = (var_type[i] == NC_CHAR) == (NCT_SHORT == NCT_TEXT);

        for (j = 0; j < var_rank[i]; j++) {
            start[j] = 0;
            edge[j] = 1;
            stride[j] = 1;
        }

        /* first test when edge[*] > 0 */
        for (j = 0; j < var_rank[i]; j++) {
            if (var_dimid[i][j] == RECDIM) continue; /* skip record dim */
            start[j] = var_shape[i][j];   /* out of boundary check */
            err = nc_put_vars_short(ncid, i, start, edge, stride, value);
            if (!canConvert) {
                IF (err != NC_ECHAR)
                    error("expecting NC_ECHAR but got %s",nc_err_code_name(err));
                ELSE_NOK
                start[j] = 0;
                continue;
            }
            IF (err != NC_EINVALCOORDS)
                error("expecting NC_EINVALCOORDS but got %s",nc_err_code_name(err));
            ELSE_NOK
            start[j] = 0;
            edge[j] = var_shape[i][j] + 1;
            err = nc_put_vars_short(ncid, i, start, edge, stride, value);
            IF (err != NC_EEDGE)
                error("expecting NC_EEDGE but got %s",nc_err_code_name(err));
            ELSE_NOK
            edge[j] = 1;
            stride[j] = 0;
            err = nc_put_vars_short(ncid, i, start, edge, stride, value);
            IF (err != NC_ESTRIDE)
                error("expecting NC_ESTRIDE but got %s",nc_err_code_name(err));
            ELSE_NOK
            stride[j] = 1;
        }
        /* Check correct error returned even when nothing to put */
        for (j = 0; j < var_rank[i]; j++) edge[j] = 0;

        for (j = 0; j < var_rank[i]; j++) {
            if (var_dimid[i][j] == RECDIM) continue; /* skip record dim */
            start[j] = var_shape[i][j];
            err = nc_put_vars_short(ncid, i, start, edge, stride, value);
            if (!canConvert) {
                IF (err != NC_ECHAR)
                    error("expecting NC_ECHAR but got %s",nc_err_code_name(err));
                ELSE_NOK
                start[j] = 0;
                continue;
            }
#ifdef RELAX_COORD_BOUND
            IF (err != NC_NOERR) /* allowed when edge[j]==0 */
                error("expecting NC_NOERR but got %s",nc_err_code_name(err));
#else
            IF (err != NC_EINVALCOORDS) /* not allowed even when edge[j]==0 */
                error("expecting NC_EINVALCOORDS but got %s",nc_err_code_name(err));
#endif
            ELSE_NOK
            start[j] = var_shape[i][j]+1; /* out of boundary check */
            err = nc_put_vars_short(ncid, i, start, edge, stride, value);
            IF (err != NC_EINVALCOORDS)
                error("expecting NC_EINVALCOORDS but got %s",nc_err_code_name(err));
            ELSE_NOK
            start[j] = 0;
        }
        for (j = 0; j < var_rank[i]; j++) edge[j] = 1;

        /* Choose a random point dividing each dim into 2 parts */
        /* Put 2^rank (nslabs) slabs so defined */
        nslabs = 1;
        for (j = 0; j < var_rank[i]; j++) {
            mid[j] = roll( var_shape[i][j] );
            nslabs *= 2;
        }
        /* bits of k determine whether to put lower or upper part of dim */
        /* choose random stride from 1 to edge */
        for (k = 0; k < nslabs; k++) {
            nstarts = 1;
            for (j = 0; j < var_rank[i]; j++) {
                if ((k >> j) & 1) {
                    start[j] = 0;
                    edge[j] = mid[j];
                } else {
                    start[j] = mid[j];
                    edge[j] = var_shape[i][j] - mid[j];
                }
                sstride[j] = edge[j] > 0 ? 1+roll(edge[j]) : 1;
                stride[j] = (ptrdiff_t)sstride[j];
                nstarts *= stride[j];
            }
            for (m = 0; m < nstarts; m++) {
                err = toMixedBase(m, var_rank[i], sstride, index);
                IF (err != 0) error("error in toMixedBase");
                nels = 1;
                for (j = 0; j < var_rank[i]; j++) {
                    count[j] = 1 + (edge[j] - index[j] - 1) / (size_t)stride[j];
                    nels *= count[j];
                    index[j] += start[j];
                }
                /* Random choice of forward or backward */
/* TODO
                if ( roll(2) ) {
                    for (j = 0; j < var_rank[i]; j++) {
                        index[j] += (count[j] - 1) * (size_t)stride[j];
                        stride[j] = -stride[j];
                    }
                }
*/
                for (allInExtRange = 1, j = 0; j < nels; j++) {
                    err = toMixedBase(j, var_rank[i], count, index2);
                    IF (err != 0) error("error in toMixedBase");
                    for (d = 0; d < var_rank[i]; d++)
                        index2[d] = index[d] + index2[d] * (size_t)stride[d];
                    value[j] = hash_short(cdf_format,var_type[i], var_rank[i],
                                       index2, NCT_SHORT);
                    
                        allInExtRange &= inRange3(cdf_format, (double)value[j],
                                                  var_type[i], NCT_SHORT);
                }
                err = nc_put_vars_short(ncid, i, index, count, stride, value);
                if (canConvert) {
                    if (allInExtRange) {
                        IF (err != NC_NOERR)
                            error("expecting NC_NOERR but got %s",nc_err_code_name(err));
                        ELSE_NOK
                    }
                    
                    else {

                        IF (err != NC_ERANGE)
                            error("expecting NC_ERANGE but got %s",nc_err_code_name(err));
                        ELSE_NOK
                    }


                } else {
                    IF (err != NC_ECHAR)
                        error("expecting NC_ECHAR but got %s",nc_err_code_name(err));
                    ELSE_NOK
                }
            }
        }
    }

    err =  nc_close(ncid);
    IF (err != NC_NOERR)
        error("close: %s",  nc_strerror(err));

    nok += check_vars_short(scratch, numVars);

    err = nc_delete(scratch);
    IF (err != NC_NOERR)
        error("delete file %s failed", scratch);
    return nok;
}

int
test_nc_put_vars_int(void)
{
    int i, k, d, err, nslabs, ncid, cdf_format, nok=0;
    int canConvert;     /* Both text or both numeric */
    int allInExtRange;  /* all values within external range? */
    size_t j, m, nels;
    size_t start[MAX_RANK], edge[MAX_RANK], index[MAX_RANK];
    size_t index2[MAX_RANK], mid[MAX_RANK], count[MAX_RANK];
    size_t sstride[MAX_RANK];
    ptrdiff_t nstarts;   /* number of different starts */
    ptrdiff_t stride[MAX_RANK];
    int value[MAX_NELS];

    err = file_create(scratch, NC_CLOBBER, &ncid);
    IF (err != NC_NOERR) {
        error("create: %s",  nc_strerror(err));
        return nok;
    }

    err =  nc_inq_format(ncid, &cdf_format);
    IF (err != NC_NOERR)
        error("inq_format: %s",  nc_strerror(err));

    def_dims(ncid);
    def_vars(ncid);

    err =  nc_enddef(ncid);
    IF (err != NC_NOERR)
        error("enddef: %s",  nc_strerror(err));

    /* check if can detect a bad file ID */
    err = nc_put_vars_int(BAD_ID, 0, NULL, NULL, NULL, NULL);
    IF (err != NC_EBADID)
        error("expecting NC_EBADID but got %s",nc_err_code_name(err));
    ELSE_NOK

    /* check if can detect a bad variable ID */
    err = nc_put_vars_int(ncid, BAD_VARID, NULL, NULL, NULL, NULL);
    IF (err != NC_ENOTVAR)
        error("expecting NC_ENOTVAR but got %s",nc_err_code_name(err));
    ELSE_NOK

    for (i = 0; i < numVars; i++) {
        assert(var_rank[i] <= MAX_RANK);
        assert(var_nels[i] <= MAX_NELS);

        value[0] = 5; /* reset to a value within bounds */

        /* check if can detect a bad file ID */
        err = nc_put_vars_int(BAD_ID, i, NULL, NULL, NULL, value);
        IF (err != NC_EBADID)
            error("expecting NC_EBADID but got %s",nc_err_code_name(err));
        ELSE_NOK

        canConvert = (var_type[i] == NC_CHAR) == (NCT_INT == NCT_TEXT);

        for (j = 0; j < var_rank[i]; j++) {
            start[j] = 0;
            edge[j] = 1;
            stride[j] = 1;
        }

        /* first test when edge[*] > 0 */
        for (j = 0; j < var_rank[i]; j++) {
            if (var_dimid[i][j] == RECDIM) continue; /* skip record dim */
            start[j] = var_shape[i][j];   /* out of boundary check */
            err = nc_put_vars_int(ncid, i, start, edge, stride, value);
            if (!canConvert) {
                IF (err != NC_ECHAR)
                    error("expecting NC_ECHAR but got %s",nc_err_code_name(err));
                ELSE_NOK
                start[j] = 0;
                continue;
            }
            IF (err != NC_EINVALCOORDS)
                error("expecting NC_EINVALCOORDS but got %s",nc_err_code_name(err));
            ELSE_NOK
            start[j] = 0;
            edge[j] = var_shape[i][j] + 1;
            err = nc_put_vars_int(ncid, i, start, edge, stride, value);
            IF (err != NC_EEDGE)
                error("expecting NC_EEDGE but got %s",nc_err_code_name(err));
            ELSE_NOK
            edge[j] = 1;
            stride[j] = 0;
            err = nc_put_vars_int(ncid, i, start, edge, stride, value);
            IF (err != NC_ESTRIDE)
                error("expecting NC_ESTRIDE but got %s",nc_err_code_name(err));
            ELSE_NOK
            stride[j] = 1;
        }
        /* Check correct error returned even when nothing to put */
        for (j = 0; j < var_rank[i]; j++) edge[j] = 0;

        for (j = 0; j < var_rank[i]; j++) {
            if (var_dimid[i][j] == RECDIM) continue; /* skip record dim */
            start[j] = var_shape[i][j];
            err = nc_put_vars_int(ncid, i, start, edge, stride, value);
            if (!canConvert) {
                IF (err != NC_ECHAR)
                    error("expecting NC_ECHAR but got %s",nc_err_code_name(err));
                ELSE_NOK
                start[j] = 0;
                continue;
            }
#ifdef RELAX_COORD_BOUND
            IF (err != NC_NOERR) /* allowed when edge[j]==0 */
                error("expecting NC_NOERR but got %s",nc_err_code_name(err));
#else
            IF (err != NC_EINVALCOORDS) /* not allowed even when edge[j]==0 */
                error("expecting NC_EINVALCOORDS but got %s",nc_err_code_name(err));
#endif
            ELSE_NOK
            start[j] = var_shape[i][j]+1; /* out of boundary check */
            err = nc_put_vars_int(ncid, i, start, edge, stride, value);
            IF (err != NC_EINVALCOORDS)
                error("expecting NC_EINVALCOORDS but got %s",nc_err_code_name(err));
            ELSE_NOK
            start[j] = 0;
        }
        for (j = 0; j < var_rank[i]; j++) edge[j] = 1;

        /* Choose a random point dividing each dim into 2 parts */
        /* Put 2^rank (nslabs) slabs so defined */
        nslabs = 1;
        for (j = 0; j < var_rank[i]; j++) {
            mid[j] = roll( var_shape[i][j] );
            nslabs *= 2;
        }
        /* bits of k determine whether to put lower or upper part of dim */
        /* choose random stride from 1 to edge */
        for (k = 0; k < nslabs; k++) {
            nstarts = 1;
            for (j = 0; j < var_rank[i]; j++) {
                if ((k >> j) & 1) {
                    start[j] = 0;
                    edge[j] = mid[j];
                } else {
                    start[j] = mid[j];
                    edge[j] = var_shape[i][j] - mid[j];
                }
                sstride[j] = edge[j] > 0 ? 1+roll(edge[j]) : 1;
                stride[j] = (ptrdiff_t)sstride[j];
                nstarts *= stride[j];
            }
            for (m = 0; m < nstarts; m++) {
                err = toMixedBase(m, var_rank[i], sstride, index);
                IF (err != 0) error("error in toMixedBase");
                nels = 1;
                for (j = 0; j < var_rank[i]; j++) {
                    count[j] = 1 + (edge[j] - index[j] - 1) / (size_t)stride[j];
                    nels *= count[j];
                    index[j] += start[j];
                }
                /* Random choice of forward or backward */
/* TODO
                if ( roll(2) ) {
                    for (j = 0; j < var_rank[i]; j++) {
                        index[j] += (count[j] - 1) * (size_t)stride[j];
                        stride[j] = -stride[j];
                    }
                }
*/
                for (allInExtRange = 1, j = 0; j < nels; j++) {
                    err = toMixedBase(j, var_rank[i], count, index2);
                    IF (err != 0) error("error in toMixedBase");
                    for (d = 0; d < var_rank[i]; d++)
                        index2[d] = index[d] + index2[d] * (size_t)stride[d];
                    value[j] = hash_int(cdf_format,var_type[i], var_rank[i],
                                       index2, NCT_INT);
                    
                        allInExtRange &= inRange3(cdf_format, (double)value[j],
                                                  var_type[i], NCT_INT);
                }
                err = nc_put_vars_int(ncid, i, index, count, stride, value);
                if (canConvert) {
                    if (allInExtRange) {
                        IF (err != NC_NOERR)
                            error("expecting NC_NOERR but got %s",nc_err_code_name(err));
                        ELSE_NOK
                    }
                    
                    else {

                        IF (err != NC_ERANGE)
                            error("expecting NC_ERANGE but got %s",nc_err_code_name(err));
                        ELSE_NOK
                    }


                } else {
                    IF (err != NC_ECHAR)
                        error("expecting NC_ECHAR but got %s",nc_err_code_name(err));
                    ELSE_NOK
                }
            }
        }
    }

    err =  nc_close(ncid);
    IF (err != NC_NOERR)
        error("close: %s",  nc_strerror(err));

    nok += check_vars_int(scratch, numVars);

    err = nc_delete(scratch);
    IF (err != NC_NOERR)
        error("delete file %s failed", scratch);
    return nok;
}

int
test_nc_put_vars_long(void)
{
    int i, k, d, err, nslabs, ncid, cdf_format, nok=0;
    int canConvert;     /* Both text or both numeric */
    int allInExtRange;  /* all values within external range? */
    size_t j, m, nels;
    size_t start[MAX_RANK], edge[MAX_RANK], index[MAX_RANK];
    size_t index2[MAX_RANK], mid[MAX_RANK], count[MAX_RANK];
    size_t sstride[MAX_RANK];
    ptrdiff_t nstarts;   /* number of different starts */
    ptrdiff_t stride[MAX_RANK];
    long value[MAX_NELS];

    err = file_create(scratch, NC_CLOBBER, &ncid);
    IF (err != NC_NOERR) {
        error("create: %s",  nc_strerror(err));
        return nok;
    }

    err =  nc_inq_format(ncid, &cdf_format);
    IF (err != NC_NOERR)
        error("inq_format: %s",  nc_strerror(err));

    def_dims(ncid);
    def_vars(ncid);

    err =  nc_enddef(ncid);
    IF (err != NC_NOERR)
        error("enddef: %s",  nc_strerror(err));

    /* check if can detect a bad file ID */
    err = nc_put_vars_long(BAD_ID, 0, NULL, NULL, NULL, NULL);
    IF (err != NC_EBADID)
        error("expecting NC_EBADID but got %s",nc_err_code_name(err));
    ELSE_NOK

    /* check if can detect a bad variable ID */
    err = nc_put_vars_long(ncid, BAD_VARID, NULL, NULL, NULL, NULL);
    IF (err != NC_ENOTVAR)
        error("expecting NC_ENOTVAR but got %s",nc_err_code_name(err));
    ELSE_NOK

    for (i = 0; i < numVars; i++) {
        assert(var_rank[i] <= MAX_RANK);
        assert(var_nels[i] <= MAX_NELS);

        value[0] = 5; /* reset to a value within bounds */

        /* check if can detect a bad file ID */
        err = nc_put_vars_long(BAD_ID, i, NULL, NULL, NULL, value);
        IF (err != NC_EBADID)
            error("expecting NC_EBADID but got %s",nc_err_code_name(err));
        ELSE_NOK

        canConvert = (var_type[i] == NC_CHAR) == (NCT_LONG == NCT_TEXT);

        for (j = 0; j < var_rank[i]; j++) {
            start[j] = 0;
            edge[j] = 1;
            stride[j] = 1;
        }

        /* first test when edge[*] > 0 */
        for (j = 0; j < var_rank[i]; j++) {
            if (var_dimid[i][j] == RECDIM) continue; /* skip record dim */
            start[j] = var_shape[i][j];   /* out of boundary check */
            err = nc_put_vars_long(ncid, i, start, edge, stride, value);
            if (!canConvert) {
                IF (err != NC_ECHAR)
                    error("expecting NC_ECHAR but got %s",nc_err_code_name(err));
                ELSE_NOK
                start[j] = 0;
                continue;
            }
            IF (err != NC_EINVALCOORDS)
                error("expecting NC_EINVALCOORDS but got %s",nc_err_code_name(err));
            ELSE_NOK
            start[j] = 0;
            edge[j] = var_shape[i][j] + 1;
            err = nc_put_vars_long(ncid, i, start, edge, stride, value);
            IF (err != NC_EEDGE)
                error("expecting NC_EEDGE but got %s",nc_err_code_name(err));
            ELSE_NOK
            edge[j] = 1;
            stride[j] = 0;
            err = nc_put_vars_long(ncid, i, start, edge, stride, value);
            IF (err != NC_ESTRIDE)
                error("expecting NC_ESTRIDE but got %s",nc_err_code_name(err));
            ELSE_NOK
            stride[j] = 1;
        }
        /* Check correct error returned even when nothing to put */
        for (j = 0; j < var_rank[i]; j++) edge[j] = 0;

        for (j = 0; j < var_rank[i]; j++) {
            if (var_dimid[i][j] == RECDIM) continue; /* skip record dim */
            start[j] = var_shape[i][j];
            err = nc_put_vars_long(ncid, i, start, edge, stride, value);
            if (!canConvert) {
                IF (err != NC_ECHAR)
                    error("expecting NC_ECHAR but got %s",nc_err_code_name(err));
                ELSE_NOK
                start[j] = 0;
                continue;
            }
#ifdef RELAX_COORD_BOUND
            IF (err != NC_NOERR) /* allowed when edge[j]==0 */
                error("expecting NC_NOERR but got %s",nc_err_code_name(err));
#else
            IF (err != NC_EINVALCOORDS) /* not allowed even when edge[j]==0 */
                error("expecting NC_EINVALCOORDS but got %s",nc_err_code_name(err));
#endif
            ELSE_NOK
            start[j] = var_shape[i][j]+1; /* out of boundary check */
            err = nc_put_vars_long(ncid, i, start, edge, stride, value);
            IF (err != NC_EINVALCOORDS)
                error("expecting NC_EINVALCOORDS but got %s",nc_err_code_name(err));
            ELSE_NOK
            start[j] = 0;
        }
        for (j = 0; j < var_rank[i]; j++) edge[j] = 1;

        /* Choose a random point dividing each dim into 2 parts */
        /* Put 2^rank (nslabs) slabs so defined */
        nslabs = 1;
        for (j = 0; j < var_rank[i]; j++) {
            mid[j] = roll( var_shape[i][j] );
            nslabs *= 2;
        }
        /* bits of k determine whether to put lower or upper part of dim */
        /* choose random stride from 1 to edge */
        for (k = 0; k < nslabs; k++) {
            nstarts = 1;
            for (j = 0; j < var_rank[i]; j++) {
                if ((k >> j) & 1) {
                    start[j] = 0;
                    edge[j] = mid[j];
                } else {
                    start[j] = mid[j];
                    edge[j] = var_shape[i][j] - mid[j];
                }
                sstride[j] = edge[j] > 0 ? 1+roll(edge[j]) : 1;
                stride[j] = (ptrdiff_t)sstride[j];
                nstarts *= stride[j];
            }
            for (m = 0; m < nstarts; m++) {
                err = toMixedBase(m, var_rank[i], sstride, index);
                IF (err != 0) error("error in toMixedBase");
                nels = 1;
                for (j = 0; j < var_rank[i]; j++) {
                    count[j] = 1 + (edge[j] - index[j] - 1) / (size_t)stride[j];
                    nels *= count[j];
                    index[j] += start[j];
                }
                /* Random choice of forward or backward */
/* TODO
                if ( roll(2) ) {
                    for (j = 0; j < var_rank[i]; j++) {
                        index[j] += (count[j] - 1) * (size_t)stride[j];
                        stride[j] = -stride[j];
                    }
                }
*/
                for (allInExtRange = 1, j = 0; j < nels; j++) {
                    err = toMixedBase(j, var_rank[i], count, index2);
                    IF (err != 0) error("error in toMixedBase");
                    for (d = 0; d < var_rank[i]; d++)
                        index2[d] = index[d] + index2[d] * (size_t)stride[d];
                    value[j] = hash_long(cdf_format,var_type[i], var_rank[i],
                                       index2, NCT_LONG);
                    
                        allInExtRange &= inRange3(cdf_format, (double)value[j],
                                                  var_type[i], NCT_LONG);
                }
                err = nc_put_vars_long(ncid, i, index, count, stride, value);
                if (canConvert) {
                    if (allInExtRange) {
                        IF (err != NC_NOERR)
                            error("expecting NC_NOERR but got %s",nc_err_code_name(err));
                        ELSE_NOK
                    }
                    
                    else {

                        IF (err != NC_ERANGE)
                            error("expecting NC_ERANGE but got %s",nc_err_code_name(err));
                        ELSE_NOK
                    }


                } else {
                    IF (err != NC_ECHAR)
                        error("expecting NC_ECHAR but got %s",nc_err_code_name(err));
                    ELSE_NOK
                }
            }
        }
    }

    err =  nc_close(ncid);
    IF (err != NC_NOERR)
        error("close: %s",  nc_strerror(err));

    nok += check_vars_long(scratch, numVars);

    err = nc_delete(scratch);
    IF (err != NC_NOERR)
        error("delete file %s failed", scratch);
    return nok;
}

int
test_nc_put_vars_float(void)
{
    int i, k, d, err, nslabs, ncid, cdf_format, nok=0;
    int canConvert;     /* Both text or both numeric */
    int allInExtRange;  /* all values within external range? */
    size_t j, m, nels;
    size_t start[MAX_RANK], edge[MAX_RANK], index[MAX_RANK];
    size_t index2[MAX_RANK], mid[MAX_RANK], count[MAX_RANK];
    size_t sstride[MAX_RANK];
    ptrdiff_t nstarts;   /* number of different starts */
    ptrdiff_t stride[MAX_RANK];
    float value[MAX_NELS];

    err = file_create(scratch, NC_CLOBBER, &ncid);
    IF (err != NC_NOERR) {
        error("create: %s",  nc_strerror(err));
        return nok;
    }

    err =  nc_inq_format(ncid, &cdf_format);
    IF (err != NC_NOERR)
        error("inq_format: %s",  nc_strerror(err));

    def_dims(ncid);
    def_vars(ncid);

    err =  nc_enddef(ncid);
    IF (err != NC_NOERR)
        error("enddef: %s",  nc_strerror(err));

    /* check if can detect a bad file ID */
    err = nc_put_vars_float(BAD_ID, 0, NULL, NULL, NULL, NULL);
    IF (err != NC_EBADID)
        error("expecting NC_EBADID but got %s",nc_err_code_name(err));
    ELSE_NOK

    /* check if can detect a bad variable ID */
    err = nc_put_vars_float(ncid, BAD_VARID, NULL, NULL, NULL, NULL);
    IF (err != NC_ENOTVAR)
        error("expecting NC_ENOTVAR but got %s",nc_err_code_name(err));
    ELSE_NOK

    for (i = 0; i < numVars; i++) {
        assert(var_rank[i] <= MAX_RANK);
        assert(var_nels[i] <= MAX_NELS);

        value[0] = 5; /* reset to a value within bounds */

        /* check if can detect a bad file ID */
        err = nc_put_vars_float(BAD_ID, i, NULL, NULL, NULL, value);
        IF (err != NC_EBADID)
            error("expecting NC_EBADID but got %s",nc_err_code_name(err));
        ELSE_NOK

        canConvert = (var_type[i] == NC_CHAR) == (NCT_FLOAT == NCT_TEXT);

        for (j = 0; j < var_rank[i]; j++) {
            start[j] = 0;
            edge[j] = 1;
            stride[j] = 1;
        }

        /* first test when edge[*] > 0 */
        for (j = 0; j < var_rank[i]; j++) {
            if (var_dimid[i][j] == RECDIM) continue; /* skip record dim */
            start[j] = var_shape[i][j];   /* out of boundary check */
            err = nc_put_vars_float(ncid, i, start, edge, stride, value);
            if (!canConvert) {
                IF (err != NC_ECHAR)
                    error("expecting NC_ECHAR but got %s",nc_err_code_name(err));
                ELSE_NOK
                start[j] = 0;
                continue;
            }
            IF (err != NC_EINVALCOORDS)
                error("expecting NC_EINVALCOORDS but got %s",nc_err_code_name(err));
            ELSE_NOK
            start[j] = 0;
            edge[j] = var_shape[i][j] + 1;
            err = nc_put_vars_float(ncid, i, start, edge, stride, value);
            IF (err != NC_EEDGE)
                error("expecting NC_EEDGE but got %s",nc_err_code_name(err));
            ELSE_NOK
            edge[j] = 1;
            stride[j] = 0;
            err = nc_put_vars_float(ncid, i, start, edge, stride, value);
            IF (err != NC_ESTRIDE)
                error("expecting NC_ESTRIDE but got %s",nc_err_code_name(err));
            ELSE_NOK
            stride[j] = 1;
        }
        /* Check correct error returned even when nothing to put */
        for (j = 0; j < var_rank[i]; j++) edge[j] = 0;

        for (j = 0; j < var_rank[i]; j++) {
            if (var_dimid[i][j] == RECDIM) continue; /* skip record dim */
            start[j] = var_shape[i][j];
            err = nc_put_vars_float(ncid, i, start, edge, stride, value);
            if (!canConvert) {
                IF (err != NC_ECHAR)
                    error("expecting NC_ECHAR but got %s",nc_err_code_name(err));
                ELSE_NOK
                start[j] = 0;
                continue;
            }
#ifdef RELAX_COORD_BOUND
            IF (err != NC_NOERR) /* allowed when edge[j]==0 */
                error("expecting NC_NOERR but got %s",nc_err_code_name(err));
#else
            IF (err != NC_EINVALCOORDS) /* not allowed even when edge[j]==0 */
                error("expecting NC_EINVALCOORDS but got %s",nc_err_code_name(err));
#endif
            ELSE_NOK
            start[j] = var_shape[i][j]+1; /* out of boundary check */
            err = nc_put_vars_float(ncid, i, start, edge, stride, value);
            IF (err != NC_EINVALCOORDS)
                error("expecting NC_EINVALCOORDS but got %s",nc_err_code_name(err));
            ELSE_NOK
            start[j] = 0;
        }
        for (j = 0; j < var_rank[i]; j++) edge[j] = 1;

        /* Choose a random point dividing each dim into 2 parts */
        /* Put 2^rank (nslabs) slabs so defined */
        nslabs = 1;
        for (j = 0; j < var_rank[i]; j++) {
            mid[j] = roll( var_shape[i][j] );
            nslabs *= 2;
        }
        /* bits of k determine whether to put lower or upper part of dim */
        /* choose random stride from 1 to edge */
        for (k = 0; k < nslabs; k++) {
            nstarts = 1;
            for (j = 0; j < var_rank[i]; j++) {
                if ((k >> j) & 1) {
                    start[j] = 0;
                    edge[j] = mid[j];
                } else {
                    start[j] = mid[j];
                    edge[j] = var_shape[i][j] - mid[j];
                }
                sstride[j] = edge[j] > 0 ? 1+roll(edge[j]) : 1;
                stride[j] = (ptrdiff_t)sstride[j];
                nstarts *= stride[j];
            }
            for (m = 0; m < nstarts; m++) {
                err = toMixedBase(m, var_rank[i], sstride, index);
                IF (err != 0) error("error in toMixedBase");
                nels = 1;
                for (j = 0; j < var_rank[i]; j++) {
                    count[j] = 1 + (edge[j] - index[j] - 1) / (size_t)stride[j];
                    nels *= count[j];
                    index[j] += start[j];
                }
                /* Random choice of forward or backward */
/* TODO
                if ( roll(2) ) {
                    for (j = 0; j < var_rank[i]; j++) {
                        index[j] += (count[j] - 1) * (size_t)stride[j];
                        stride[j] = -stride[j];
                    }
                }
*/
                for (allInExtRange = 1, j = 0; j < nels; j++) {
                    err = toMixedBase(j, var_rank[i], count, index2);
                    IF (err != 0) error("error in toMixedBase");
                    for (d = 0; d < var_rank[i]; d++)
                        index2[d] = index[d] + index2[d] * (size_t)stride[d];
                    value[j] = hash_float(cdf_format,var_type[i], var_rank[i],
                                       index2, NCT_FLOAT);
                    
                        allInExtRange &= inRange3(cdf_format, (double)value[j],
                                                  var_type[i], NCT_FLOAT);
                }
                err = nc_put_vars_float(ncid, i, index, count, stride, value);
                if (canConvert) {
                    if (allInExtRange) {
                        IF (err != NC_NOERR)
                            error("expecting NC_NOERR but got %s",nc_err_code_name(err));
                        ELSE_NOK
                    }
                    
                    else {

                        IF (err != NC_ERANGE)
                            error("expecting NC_ERANGE but got %s",nc_err_code_name(err));
                        ELSE_NOK
                    }


                } else {
                    IF (err != NC_ECHAR)
                        error("expecting NC_ECHAR but got %s",nc_err_code_name(err));
                    ELSE_NOK
                }
            }
        }
    }

    err =  nc_close(ncid);
    IF (err != NC_NOERR)
        error("close: %s",  nc_strerror(err));

    nok += check_vars_float(scratch, numVars);

    err = nc_delete(scratch);
    IF (err != NC_NOERR)
        error("delete file %s failed", scratch);
    return nok;
}

int
test_nc_put_vars_double(void)
{
    int i, k, d, err, nslabs, ncid, cdf_format, nok=0;
    int canConvert;     /* Both text or both numeric */
    int allInExtRange;  /* all values within external range? */
    size_t j, m, nels;
    size_t start[MAX_RANK], edge[MAX_RANK], index[MAX_RANK];
    size_t index2[MAX_RANK], mid[MAX_RANK], count[MAX_RANK];
    size_t sstride[MAX_RANK];
    ptrdiff_t nstarts;   /* number of different starts */
    ptrdiff_t stride[MAX_RANK];
    double value[MAX_NELS];

    err = file_create(scratch, NC_CLOBBER, &ncid);
    IF (err != NC_NOERR) {
        error("create: %s",  nc_strerror(err));
        return nok;
    }

    err =  nc_inq_format(ncid, &cdf_format);
    IF (err != NC_NOERR)
        error("inq_format: %s",  nc_strerror(err));

    def_dims(ncid);
    def_vars(ncid);

    err =  nc_enddef(ncid);
    IF (err != NC_NOERR)
        error("enddef: %s",  nc_strerror(err));

    /* check if can detect a bad file ID */
    err = nc_put_vars_double(BAD_ID, 0, NULL, NULL, NULL, NULL);
    IF (err != NC_EBADID)
        error("expecting NC_EBADID but got %s",nc_err_code_name(err));
    ELSE_NOK

    /* check if can detect a bad variable ID */
    err = nc_put_vars_double(ncid, BAD_VARID, NULL, NULL, NULL, NULL);
    IF (err != NC_ENOTVAR)
        error("expecting NC_ENOTVAR but got %s",nc_err_code_name(err));
    ELSE_NOK

    for (i = 0; i < numVars; i++) {
        assert(var_rank[i] <= MAX_RANK);
        assert(var_nels[i] <= MAX_NELS);

        value[0] = 5; /* reset to a value within bounds */

        /* check if can detect a bad file ID */
        err = nc_put_vars_double(BAD_ID, i, NULL, NULL, NULL, value);
        IF (err != NC_EBADID)
            error("expecting NC_EBADID but got %s",nc_err_code_name(err));
        ELSE_NOK

        canConvert = (var_type[i] == NC_CHAR) == (NCT_DOUBLE == NCT_TEXT);

        for (j = 0; j < var_rank[i]; j++) {
            start[j] = 0;
            edge[j] = 1;
            stride[j] = 1;
        }

        /* first test when edge[*] > 0 */
        for (j = 0; j < var_rank[i]; j++) {
            if (var_dimid[i][j] == RECDIM) continue; /* skip record dim */
            start[j] = var_shape[i][j];   /* out of boundary check */
            err = nc_put_vars_double(ncid, i, start, edge, stride, value);
            if (!canConvert) {
                IF (err != NC_ECHAR)
                    error("expecting NC_ECHAR but got %s",nc_err_code_name(err));
                ELSE_NOK
                start[j] = 0;
                continue;
            }
            IF (err != NC_EINVALCOORDS)
                error("expecting NC_EINVALCOORDS but got %s",nc_err_code_name(err));
            ELSE_NOK
            start[j] = 0;
            edge[j] = var_shape[i][j] + 1;
            err = nc_put_vars_double(ncid, i, start, edge, stride, value);
            IF (err != NC_EEDGE)
                error("expecting NC_EEDGE but got %s",nc_err_code_name(err));
            ELSE_NOK
            edge[j] = 1;
            stride[j] = 0;
            err = nc_put_vars_double(ncid, i, start, edge, stride, value);
            IF (err != NC_ESTRIDE)
                error("expecting NC_ESTRIDE but got %s",nc_err_code_name(err));
            ELSE_NOK
            stride[j] = 1;
        }
        /* Check correct error returned even when nothing to put */
        for (j = 0; j < var_rank[i]; j++) edge[j] = 0;

        for (j = 0; j < var_rank[i]; j++) {
            if (var_dimid[i][j] == RECDIM) continue; /* skip record dim */
            start[j] = var_shape[i][j];
            err = nc_put_vars_double(ncid, i, start, edge, stride, value);
            if (!canConvert) {
                IF (err != NC_ECHAR)
                    error("expecting NC_ECHAR but got %s",nc_err_code_name(err));
                ELSE_NOK
                start[j] = 0;
                continue;
            }
#ifdef RELAX_COORD_BOUND
            IF (err != NC_NOERR) /* allowed when edge[j]==0 */
                error("expecting NC_NOERR but got %s",nc_err_code_name(err));
#else
            IF (err != NC_EINVALCOORDS) /* not allowed even when edge[j]==0 */
                error("expecting NC_EINVALCOORDS but got %s",nc_err_code_name(err));
#endif
            ELSE_NOK
            start[j] = var_shape[i][j]+1; /* out of boundary check */
            err = nc_put_vars_double(ncid, i, start, edge, stride, value);
            IF (err != NC_EINVALCOORDS)
                error("expecting NC_EINVALCOORDS but got %s",nc_err_code_name(err));
            ELSE_NOK
            start[j] = 0;
        }
        for (j = 0; j < var_rank[i]; j++) edge[j] = 1;

        /* Choose a random point dividing each dim into 2 parts */
        /* Put 2^rank (nslabs) slabs so defined */
        nslabs = 1;
        for (j = 0; j < var_rank[i]; j++) {
            mid[j] = roll( var_shape[i][j] );
            nslabs *= 2;
        }
        /* bits of k determine whether to put lower or upper part of dim */
        /* choose random stride from 1 to edge */
        for (k = 0; k < nslabs; k++) {
            nstarts = 1;
            for (j = 0; j < var_rank[i]; j++) {
                if ((k >> j) & 1) {
                    start[j] = 0;
                    edge[j] = mid[j];
                } else {
                    start[j] = mid[j];
                    edge[j] = var_shape[i][j] - mid[j];
                }
                sstride[j] = edge[j] > 0 ? 1+roll(edge[j]) : 1;
                stride[j] = (ptrdiff_t)sstride[j];
                nstarts *= stride[j];
            }
            for (m = 0; m < nstarts; m++) {
                err = toMixedBase(m, var_rank[i], sstride, index);
                IF (err != 0) error("error in toMixedBase");
                nels = 1;
                for (j = 0; j < var_rank[i]; j++) {
                    count[j] = 1 + (edge[j] - index[j] - 1) / (size_t)stride[j];
                    nels *= count[j];
                    index[j] += start[j];
                }
                /* Random choice of forward or backward */
/* TODO
                if ( roll(2) ) {
                    for (j = 0; j < var_rank[i]; j++) {
                        index[j] += (count[j] - 1) * (size_t)stride[j];
                        stride[j] = -stride[j];
                    }
                }
*/
                for (allInExtRange = 1, j = 0; j < nels; j++) {
                    err = toMixedBase(j, var_rank[i], count, index2);
                    IF (err != 0) error("error in toMixedBase");
                    for (d = 0; d < var_rank[i]; d++)
                        index2[d] = index[d] + index2[d] * (size_t)stride[d];
                    value[j] = hash_double(cdf_format,var_type[i], var_rank[i],
                                       index2, NCT_DOUBLE);
                    
                        allInExtRange &= inRange3(cdf_format, (double)value[j],
                                                  var_type[i], NCT_DOUBLE);
                }
                err = nc_put_vars_double(ncid, i, index, count, stride, value);
                if (canConvert) {
                    if (allInExtRange) {
                        IF (err != NC_NOERR)
                            error("expecting NC_NOERR but got %s",nc_err_code_name(err));
                        ELSE_NOK
                    }
                    
                    else {

                        IF (err != NC_ERANGE)
                            error("expecting NC_ERANGE but got %s",nc_err_code_name(err));
                        ELSE_NOK
                    }


                } else {
                    IF (err != NC_ECHAR)
                        error("expecting NC_ECHAR but got %s",nc_err_code_name(err));
                    ELSE_NOK
                }
            }
        }
    }

    err =  nc_close(ncid);
    IF (err != NC_NOERR)
        error("close: %s",  nc_strerror(err));

    nok += check_vars_double(scratch, numVars);

    err = nc_delete(scratch);
    IF (err != NC_NOERR)
        error("delete file %s failed", scratch);
    return nok;
}

int
test_nc_put_vars_ushort(void)
{
    int i, k, d, err, nslabs, ncid, cdf_format, nok=0;
    int canConvert;     /* Both text or both numeric */
    int allInExtRange;  /* all values within external range? */
    size_t j, m, nels;
    size_t start[MAX_RANK], edge[MAX_RANK], index[MAX_RANK];
    size_t index2[MAX_RANK], mid[MAX_RANK], count[MAX_RANK];
    size_t sstride[MAX_RANK];
    ptrdiff_t nstarts;   /* number of different starts */
    ptrdiff_t stride[MAX_RANK];
    ushort value[MAX_NELS];

    err = file_create(scratch, NC_CLOBBER, &ncid);
    IF (err != NC_NOERR) {
        error("create: %s",  nc_strerror(err));
        return nok;
    }

    err =  nc_inq_format(ncid, &cdf_format);
    IF (err != NC_NOERR)
        error("inq_format: %s",  nc_strerror(err));

    def_dims(ncid);
    def_vars(ncid);

    err =  nc_enddef(ncid);
    IF (err != NC_NOERR)
        error("enddef: %s",  nc_strerror(err));

    /* check if can detect a bad file ID */
    err = nc_put_vars_ushort(BAD_ID, 0, NULL, NULL, NULL, NULL);
    IF (err != NC_EBADID)
        error("expecting NC_EBADID but got %s",nc_err_code_name(err));
    ELSE_NOK

    /* check if can detect a bad variable ID */
    err = nc_put_vars_ushort(ncid, BAD_VARID, NULL, NULL, NULL, NULL);
    IF (err != NC_ENOTVAR)
        error("expecting NC_ENOTVAR but got %s",nc_err_code_name(err));
    ELSE_NOK

    for (i = 0; i < numVars; i++) {
        assert(var_rank[i] <= MAX_RANK);
        assert(var_nels[i] <= MAX_NELS);

        value[0] = 5; /* reset to a value within bounds */

        /* check if can detect a bad file ID */
        err = nc_put_vars_ushort(BAD_ID, i, NULL, NULL, NULL, value);
        IF (err != NC_EBADID)
            error("expecting NC_EBADID but got %s",nc_err_code_name(err));
        ELSE_NOK

        canConvert = (var_type[i] == NC_CHAR) == (NCT_USHORT == NCT_TEXT);

        for (j = 0; j < var_rank[i]; j++) {
            start[j] = 0;
            edge[j] = 1;
            stride[j] = 1;
        }

        /* first test when edge[*] > 0 */
        for (j = 0; j < var_rank[i]; j++) {
            if (var_dimid[i][j] == RECDIM) continue; /* skip record dim */
            start[j] = var_shape[i][j];   /* out of boundary check */
            err = nc_put_vars_ushort(ncid, i, start, edge, stride, value);
            if (!canConvert) {
                IF (err != NC_ECHAR)
                    error("expecting NC_ECHAR but got %s",nc_err_code_name(err));
                ELSE_NOK
                start[j] = 0;
                continue;
            }
            IF (err != NC_EINVALCOORDS)
                error("expecting NC_EINVALCOORDS but got %s",nc_err_code_name(err));
            ELSE_NOK
            start[j] = 0;
            edge[j] = var_shape[i][j] + 1;
            err = nc_put_vars_ushort(ncid, i, start, edge, stride, value);
            IF (err != NC_EEDGE)
                error("expecting NC_EEDGE but got %s",nc_err_code_name(err));
            ELSE_NOK
            edge[j] = 1;
            stride[j] = 0;
            err = nc_put_vars_ushort(ncid, i, start, edge, stride, value);
            IF (err != NC_ESTRIDE)
                error("expecting NC_ESTRIDE but got %s",nc_err_code_name(err));
            ELSE_NOK
            stride[j] = 1;
        }
        /* Check correct error returned even when nothing to put */
        for (j = 0; j < var_rank[i]; j++) edge[j] = 0;

        for (j = 0; j < var_rank[i]; j++) {
            if (var_dimid[i][j] == RECDIM) continue; /* skip record dim */
            start[j] = var_shape[i][j];
            err = nc_put_vars_ushort(ncid, i, start, edge, stride, value);
            if (!canConvert) {
                IF (err != NC_ECHAR)
                    error("expecting NC_ECHAR but got %s",nc_err_code_name(err));
                ELSE_NOK
                start[j] = 0;
                continue;
            }
#ifdef RELAX_COORD_BOUND
            IF (err != NC_NOERR) /* allowed when edge[j]==0 */
                error("expecting NC_NOERR but got %s",nc_err_code_name(err));
#else
            IF (err != NC_EINVALCOORDS) /* not allowed even when edge[j]==0 */
                error("expecting NC_EINVALCOORDS but got %s",nc_err_code_name(err));
#endif
            ELSE_NOK
            start[j] = var_shape[i][j]+1; /* out of boundary check */
            err = nc_put_vars_ushort(ncid, i, start, edge, stride, value);
            IF (err != NC_EINVALCOORDS)
                error("expecting NC_EINVALCOORDS but got %s",nc_err_code_name(err));
            ELSE_NOK
            start[j] = 0;
        }
        for (j = 0; j < var_rank[i]; j++) edge[j] = 1;

        /* Choose a random point dividing each dim into 2 parts */
        /* Put 2^rank (nslabs) slabs so defined */
        nslabs = 1;
        for (j = 0; j < var_rank[i]; j++) {
            mid[j] = roll( var_shape[i][j] );
            nslabs *= 2;
        }
        /* bits of k determine whether to put lower or upper part of dim */
        /* choose random stride from 1 to edge */
        for (k = 0; k < nslabs; k++) {
            nstarts = 1;
            for (j = 0; j < var_rank[i]; j++) {
                if ((k >> j) & 1) {
                    start[j] = 0;
                    edge[j] = mid[j];
                } else {
                    start[j] = mid[j];
                    edge[j] = var_shape[i][j] - mid[j];
                }
                sstride[j] = edge[j] > 0 ? 1+roll(edge[j]) : 1;
                stride[j] = (ptrdiff_t)sstride[j];
                nstarts *= stride[j];
            }
            for (m = 0; m < nstarts; m++) {
                err = toMixedBase(m, var_rank[i], sstride, index);
                IF (err != 0) error("error in toMixedBase");
                nels = 1;
                for (j = 0; j < var_rank[i]; j++) {
                    count[j] = 1 + (edge[j] - index[j] - 1) / (size_t)stride[j];
                    nels *= count[j];
                    index[j] += start[j];
                }
                /* Random choice of forward or backward */
/* TODO
                if ( roll(2) ) {
                    for (j = 0; j < var_rank[i]; j++) {
                        index[j] += (count[j] - 1) * (size_t)stride[j];
                        stride[j] = -stride[j];
                    }
                }
*/
                for (allInExtRange = 1, j = 0; j < nels; j++) {
                    err = toMixedBase(j, var_rank[i], count, index2);
                    IF (err != 0) error("error in toMixedBase");
                    for (d = 0; d < var_rank[i]; d++)
                        index2[d] = index[d] + index2[d] * (size_t)stride[d];
                    value[j] = hash_ushort(cdf_format,var_type[i], var_rank[i],
                                       index2, NCT_USHORT);
                    
                        allInExtRange &= inRange3(cdf_format, (double)value[j],
                                                  var_type[i], NCT_USHORT);
                }
                err = nc_put_vars_ushort(ncid, i, index, count, stride, value);
                if (canConvert) {
                    if (allInExtRange) {
                        IF (err != NC_NOERR)
                            error("expecting NC_NOERR but got %s",nc_err_code_name(err));
                        ELSE_NOK
                    }
                    
                    else {

                        IF (err != NC_ERANGE)
                            error("expecting NC_ERANGE but got %s",nc_err_code_name(err));
                        ELSE_NOK
                    }


                } else {
                    IF (err != NC_ECHAR)
                        error("expecting NC_ECHAR but got %s",nc_err_code_name(err));
                    ELSE_NOK
                }
            }
        }
    }

    err =  nc_close(ncid);
    IF (err != NC_NOERR)
        error("close: %s",  nc_strerror(err));

    nok += check_vars_ushort(scratch, numVars);

    err = nc_delete(scratch);
    IF (err != NC_NOERR)
        error("delete file %s failed", scratch);
    return nok;
}

int
test_nc_put_vars_uint(void)
{
    int i, k, d, err, nslabs, ncid, cdf_format, nok=0;
    int canConvert;     /* Both text or both numeric */
    int allInExtRange;  /* all values within external range? */
    size_t j, m, nels;
    size_t start[MAX_RANK], edge[MAX_RANK], index[MAX_RANK];
    size_t index2[MAX_RANK], mid[MAX_RANK], count[MAX_RANK];
    size_t sstride[MAX_RANK];
    ptrdiff_t nstarts;   /* number of different starts */
    ptrdiff_t stride[MAX_RANK];
    uint value[MAX_NELS];

    err = file_create(scratch, NC_CLOBBER, &ncid);
    IF (err != NC_NOERR) {
        error("create: %s",  nc_strerror(err));
        return nok;
    }

    err =  nc_inq_format(ncid, &cdf_format);
    IF (err != NC_NOERR)
        error("inq_format: %s",  nc_strerror(err));

    def_dims(ncid);
    def_vars(ncid);

    err =  nc_enddef(ncid);
    IF (err != NC_NOERR)
        error("enddef: %s",  nc_strerror(err));

    /* check if can detect a bad file ID */
    err = nc_put_vars_uint(BAD_ID, 0, NULL, NULL, NULL, NULL);
    IF (err != NC_EBADID)
        error("expecting NC_EBADID but got %s",nc_err_code_name(err));
    ELSE_NOK

    /* check if can detect a bad variable ID */
    err = nc_put_vars_uint(ncid, BAD_VARID, NULL, NULL, NULL, NULL);
    IF (err != NC_ENOTVAR)
        error("expecting NC_ENOTVAR but got %s",nc_err_code_name(err));
    ELSE_NOK

    for (i = 0; i < numVars; i++) {
        assert(var_rank[i] <= MAX_RANK);
        assert(var_nels[i] <= MAX_NELS);

        value[0] = 5; /* reset to a value within bounds */

        /* check if can detect a bad file ID */
        err = nc_put_vars_uint(BAD_ID, i, NULL, NULL, NULL, value);
        IF (err != NC_EBADID)
            error("expecting NC_EBADID but got %s",nc_err_code_name(err));
        ELSE_NOK

        canConvert = (var_type[i] == NC_CHAR) == (NCT_UINT == NCT_TEXT);

        for (j = 0; j < var_rank[i]; j++) {
            start[j] = 0;
            edge[j] = 1;
            stride[j] = 1;
        }

        /* first test when edge[*] > 0 */
        for (j = 0; j < var_rank[i]; j++) {
            if (var_dimid[i][j] == RECDIM) continue; /* skip record dim */
            start[j] = var_shape[i][j];   /* out of boundary check */
            err = nc_put_vars_uint(ncid, i, start, edge, stride, value);
            if (!canConvert) {
                IF (err != NC_ECHAR)
                    error("expecting NC_ECHAR but got %s",nc_err_code_name(err));
                ELSE_NOK
                start[j] = 0;
                continue;
            }
            IF (err != NC_EINVALCOORDS)
                error("expecting NC_EINVALCOORDS but got %s",nc_err_code_name(err));
            ELSE_NOK
            start[j] = 0;
            edge[j] = var_shape[i][j] + 1;
            err = nc_put_vars_uint(ncid, i, start, edge, stride, value);
            IF (err != NC_EEDGE)
                error("expecting NC_EEDGE but got %s",nc_err_code_name(err));
            ELSE_NOK
            edge[j] = 1;
            stride[j] = 0;
            err = nc_put_vars_uint(ncid, i, start, edge, stride, value);
            IF (err != NC_ESTRIDE)
                error("expecting NC_ESTRIDE but got %s",nc_err_code_name(err));
            ELSE_NOK
            stride[j] = 1;
        }
        /* Check correct error returned even when nothing to put */
        for (j = 0; j < var_rank[i]; j++) edge[j] = 0;

        for (j = 0; j < var_rank[i]; j++) {
            if (var_dimid[i][j] == RECDIM) continue; /* skip record dim */
            start[j] = var_shape[i][j];
            err = nc_put_vars_uint(ncid, i, start, edge, stride, value);
            if (!canConvert) {
                IF (err != NC_ECHAR)
                    error("expecting NC_ECHAR but got %s",nc_err_code_name(err));
                ELSE_NOK
                start[j] = 0;
                continue;
            }
#ifdef RELAX_COORD_BOUND
            IF (err != NC_NOERR) /* allowed when edge[j]==0 */
                error("expecting NC_NOERR but got %s",nc_err_code_name(err));
#else
            IF (err != NC_EINVALCOORDS) /* not allowed even when edge[j]==0 */
                error("expecting NC_EINVALCOORDS but got %s",nc_err_code_name(err));
#endif
            ELSE_NOK
            start[j] = var_shape[i][j]+1; /* out of boundary check */
            err = nc_put_vars_uint(ncid, i, start, edge, stride, value);
            IF (err != NC_EINVALCOORDS)
                error("expecting NC_EINVALCOORDS but got %s",nc_err_code_name(err));
            ELSE_NOK
            start[j] = 0;
        }
        for (j = 0; j < var_rank[i]; j++) edge[j] = 1;

        /* Choose a random point dividing each dim into 2 parts */
        /* Put 2^rank (nslabs) slabs so defined */
        nslabs = 1;
        for (j = 0; j < var_rank[i]; j++) {
            mid[j] = roll( var_shape[i][j] );
            nslabs *= 2;
        }
        /* bits of k determine whether to put lower or upper part of dim */
        /* choose random stride from 1 to edge */
        for (k = 0; k < nslabs; k++) {
            nstarts = 1;
            for (j = 0; j < var_rank[i]; j++) {
                if ((k >> j) & 1) {
                    start[j] = 0;
                    edge[j] = mid[j];
                } else {
                    start[j] = mid[j];
                    edge[j] = var_shape[i][j] - mid[j];
                }
                sstride[j] = edge[j] > 0 ? 1+roll(edge[j]) : 1;
                stride[j] = (ptrdiff_t)sstride[j];
                nstarts *= stride[j];
            }
            for (m = 0; m < nstarts; m++) {
                err = toMixedBase(m, var_rank[i], sstride, index);
                IF (err != 0) error("error in toMixedBase");
                nels = 1;
                for (j = 0; j < var_rank[i]; j++) {
                    count[j] = 1 + (edge[j] - index[j] - 1) / (size_t)stride[j];
                    nels *= count[j];
                    index[j] += start[j];
                }
                /* Random choice of forward or backward */
/* TODO
                if ( roll(2) ) {
                    for (j = 0; j < var_rank[i]; j++) {
                        index[j] += (count[j] - 1) * (size_t)stride[j];
                        stride[j] = -stride[j];
                    }
                }
*/
                for (allInExtRange = 1, j = 0; j < nels; j++) {
                    err = toMixedBase(j, var_rank[i], count, index2);
                    IF (err != 0) error("error in toMixedBase");
                    for (d = 0; d < var_rank[i]; d++)
                        index2[d] = index[d] + index2[d] * (size_t)stride[d];
                    value[j] = hash_uint(cdf_format,var_type[i], var_rank[i],
                                       index2, NCT_UINT);
                    
                        allInExtRange &= inRange3(cdf_format, (double)value[j],
                                                  var_type[i], NCT_UINT);
                }
                err = nc_put_vars_uint(ncid, i, index, count, stride, value);
                if (canConvert) {
                    if (allInExtRange) {
                        IF (err != NC_NOERR)
                            error("expecting NC_NOERR but got %s",nc_err_code_name(err));
                        ELSE_NOK
                    }
                    
                    else {

                        IF (err != NC_ERANGE)
                            error("expecting NC_ERANGE but got %s",nc_err_code_name(err));
                        ELSE_NOK
                    }


                } else {
                    IF (err != NC_ECHAR)
                        error("expecting NC_ECHAR but got %s",nc_err_code_name(err));
                    ELSE_NOK
                }
            }
        }
    }

    err =  nc_close(ncid);
    IF (err != NC_NOERR)
        error("close: %s",  nc_strerror(err));

    nok += check_vars_uint(scratch, numVars);

    err = nc_delete(scratch);
    IF (err != NC_NOERR)
        error("delete file %s failed", scratch);
    return nok;
}

int
test_nc_put_vars_longlong(void)
{
    int i, k, d, err, nslabs, ncid, cdf_format, nok=0;
    int canConvert;     /* Both text or both numeric */
    int allInExtRange;  /* all values within external range? */
    size_t j, m, nels;
    size_t start[MAX_RANK], edge[MAX_RANK], index[MAX_RANK];
    size_t index2[MAX_RANK], mid[MAX_RANK], count[MAX_RANK];
    size_t sstride[MAX_RANK];
    ptrdiff_t nstarts;   /* number of different starts */
    ptrdiff_t stride[MAX_RANK];
    longlong value[MAX_NELS];

    err = file_create(scratch, NC_CLOBBER, &ncid);
    IF (err != NC_NOERR) {
        error("create: %s",  nc_strerror(err));
        return nok;
    }

    err =  nc_inq_format(ncid, &cdf_format);
    IF (err != NC_NOERR)
        error("inq_format: %s",  nc_strerror(err));

    def_dims(ncid);
    def_vars(ncid);

    err =  nc_enddef(ncid);
    IF (err != NC_NOERR)
        error("enddef: %s",  nc_strerror(err));

    /* check if can detect a bad file ID */
    err = nc_put_vars_longlong(BAD_ID, 0, NULL, NULL, NULL, NULL);
    IF (err != NC_EBADID)
        error("expecting NC_EBADID but got %s",nc_err_code_name(err));
    ELSE_NOK

    /* check if can detect a bad variable ID */
    err = nc_put_vars_longlong(ncid, BAD_VARID, NULL, NULL, NULL, NULL);
    IF (err != NC_ENOTVAR)
        error("expecting NC_ENOTVAR but got %s",nc_err_code_name(err));
    ELSE_NOK

    for (i = 0; i < numVars; i++) {
        assert(var_rank[i] <= MAX_RANK);
        assert(var_nels[i] <= MAX_NELS);

        value[0] = 5; /* reset to a value within bounds */

        /* check if can detect a bad file ID */
        err = nc_put_vars_longlong(BAD_ID, i, NULL, NULL, NULL, value);
        IF (err != NC_EBADID)
            error("expecting NC_EBADID but got %s",nc_err_code_name(err));
        ELSE_NOK

        canConvert = (var_type[i] == NC_CHAR) == (NCT_LONGLONG == NCT_TEXT);

        for (j = 0; j < var_rank[i]; j++) {
            start[j] = 0;
            edge[j] = 1;
            stride[j] = 1;
        }

        /* first test when edge[*] > 0 */
        for (j = 0; j < var_rank[i]; j++) {
            if (var_dimid[i][j] == RECDIM) continue; /* skip record dim */
            start[j] = var_shape[i][j];   /* out of boundary check */
            err = nc_put_vars_longlong(ncid, i, start, edge, stride, value);
            if (!canConvert) {
                IF (err != NC_ECHAR)
                    error("expecting NC_ECHAR but got %s",nc_err_code_name(err));
                ELSE_NOK
                start[j] = 0;
                continue;
            }
            IF (err != NC_EINVALCOORDS)
                error("expecting NC_EINVALCOORDS but got %s",nc_err_code_name(err));
            ELSE_NOK
            start[j] = 0;
            edge[j] = var_shape[i][j] + 1;
            err = nc_put_vars_longlong(ncid, i, start, edge, stride, value);
            IF (err != NC_EEDGE)
                error("expecting NC_EEDGE but got %s",nc_err_code_name(err));
            ELSE_NOK
            edge[j] = 1;
            stride[j] = 0;
            err = nc_put_vars_longlong(ncid, i, start, edge, stride, value);
            IF (err != NC_ESTRIDE)
                error("expecting NC_ESTRIDE but got %s",nc_err_code_name(err));
            ELSE_NOK
            stride[j] = 1;
        }
        /* Check correct error returned even when nothing to put */
        for (j = 0; j < var_rank[i]; j++) edge[j] = 0;

        for (j = 0; j < var_rank[i]; j++) {
            if (var_dimid[i][j] == RECDIM) continue; /* skip record dim */
            start[j] = var_shape[i][j];
            err = nc_put_vars_longlong(ncid, i, start, edge, stride, value);
            if (!canConvert) {
                IF (err != NC_ECHAR)
                    error("expecting NC_ECHAR but got %s",nc_err_code_name(err));
                ELSE_NOK
                start[j] = 0;
                continue;
            }
#ifdef RELAX_COORD_BOUND
            IF (err != NC_NOERR) /* allowed when edge[j]==0 */
                error("expecting NC_NOERR but got %s",nc_err_code_name(err));
#else
            IF (err != NC_EINVALCOORDS) /* not allowed even when edge[j]==0 */
                error("expecting NC_EINVALCOORDS but got %s",nc_err_code_name(err));
#endif
            ELSE_NOK
            start[j] = var_shape[i][j]+1; /* out of boundary check */
            err = nc_put_vars_longlong(ncid, i, start, edge, stride, value);
            IF (err != NC_EINVALCOORDS)
                error("expecting NC_EINVALCOORDS but got %s",nc_err_code_name(err));
            ELSE_NOK
            start[j] = 0;
        }
        for (j = 0; j < var_rank[i]; j++) edge[j] = 1;

        /* Choose a random point dividing each dim into 2 parts */
        /* Put 2^rank (nslabs) slabs so defined */
        nslabs = 1;
        for (j = 0; j < var_rank[i]; j++) {
            mid[j] = roll( var_shape[i][j] );
            nslabs *= 2;
        }
        /* bits of k determine whether to put lower or upper part of dim */
        /* choose random stride from 1 to edge */
        for (k = 0; k < nslabs; k++) {
            nstarts = 1;
            for (j = 0; j < var_rank[i]; j++) {
                if ((k >> j) & 1) {
                    start[j] = 0;
                    edge[j] = mid[j];
                } else {
                    start[j] = mid[j];
                    edge[j] = var_shape[i][j] - mid[j];
                }
                sstride[j] = edge[j] > 0 ? 1+roll(edge[j]) : 1;
                stride[j] = (ptrdiff_t)sstride[j];
                nstarts *= stride[j];
            }
            for (m = 0; m < nstarts; m++) {
                err = toMixedBase(m, var_rank[i], sstride, index);
                IF (err != 0) error("error in toMixedBase");
                nels = 1;
                for (j = 0; j < var_rank[i]; j++) {
                    count[j] = 1 + (edge[j] - index[j] - 1) / (size_t)stride[j];
                    nels *= count[j];
                    index[j] += start[j];
                }
                /* Random choice of forward or backward */
/* TODO
                if ( roll(2) ) {
                    for (j = 0; j < var_rank[i]; j++) {
                        index[j] += (count[j] - 1) * (size_t)stride[j];
                        stride[j] = -stride[j];
                    }
                }
*/
                for (allInExtRange = 1, j = 0; j < nels; j++) {
                    err = toMixedBase(j, var_rank[i], count, index2);
                    IF (err != 0) error("error in toMixedBase");
                    for (d = 0; d < var_rank[i]; d++)
                        index2[d] = index[d] + index2[d] * (size_t)stride[d];
                    value[j] = hash_longlong(cdf_format,var_type[i], var_rank[i],
                                       index2, NCT_LONGLONG);
                    
                        allInExtRange &= inRange3(cdf_format, (double)value[j],
                                                  var_type[i], NCT_LONGLONG);
                }
                err = nc_put_vars_longlong(ncid, i, index, count, stride, value);
                if (canConvert) {
                    if (allInExtRange) {
                        IF (err != NC_NOERR)
                            error("expecting NC_NOERR but got %s",nc_err_code_name(err));
                        ELSE_NOK
                    }
                    
                    else {

                        IF (err != NC_ERANGE)
                            error("expecting NC_ERANGE but got %s",nc_err_code_name(err));
                        ELSE_NOK
                    }


                } else {
                    IF (err != NC_ECHAR)
                        error("expecting NC_ECHAR but got %s",nc_err_code_name(err));
                    ELSE_NOK
                }
            }
        }
    }

    err =  nc_close(ncid);
    IF (err != NC_NOERR)
        error("close: %s",  nc_strerror(err));

    nok += check_vars_longlong(scratch, numVars);

    err = nc_delete(scratch);
    IF (err != NC_NOERR)
        error("delete file %s failed", scratch);
    return nok;
}

int
test_nc_put_vars_ulonglong(void)
{
    int i, k, d, err, nslabs, ncid, cdf_format, nok=0;
    int canConvert;     /* Both text or both numeric */
    int allInExtRange;  /* all values within external range? */
    size_t j, m, nels;
    size_t start[MAX_RANK], edge[MAX_RANK], index[MAX_RANK];
    size_t index2[MAX_RANK], mid[MAX_RANK], count[MAX_RANK];
    size_t sstride[MAX_RANK];
    ptrdiff_t nstarts;   /* number of different starts */
    ptrdiff_t stride[MAX_RANK];
    ulonglong value[MAX_NELS];

    err = file_create(scratch, NC_CLOBBER, &ncid);
    IF (err != NC_NOERR) {
        error("create: %s",  nc_strerror(err));
        return nok;
    }

    err =  nc_inq_format(ncid, &cdf_format);
    IF (err != NC_NOERR)
        error("inq_format: %s",  nc_strerror(err));

    def_dims(ncid);
    def_vars(ncid);

    err =  nc_enddef(ncid);
    IF (err != NC_NOERR)
        error("enddef: %s",  nc_strerror(err));

    /* check if can detect a bad file ID */
    err = nc_put_vars_ulonglong(BAD_ID, 0, NULL, NULL, NULL, NULL);
    IF (err != NC_EBADID)
        error("expecting NC_EBADID but got %s",nc_err_code_name(err));
    ELSE_NOK

    /* check if can detect a bad variable ID */
    err = nc_put_vars_ulonglong(ncid, BAD_VARID, NULL, NULL, NULL, NULL);
    IF (err != NC_ENOTVAR)
        error("expecting NC_ENOTVAR but got %s",nc_err_code_name(err));
    ELSE_NOK

    for (i = 0; i < numVars; i++) {
        assert(var_rank[i] <= MAX_RANK);
        assert(var_nels[i] <= MAX_NELS);

        value[0] = 5; /* reset to a value within bounds */

        /* check if can detect a bad file ID */
        err = nc_put_vars_ulonglong(BAD_ID, i, NULL, NULL, NULL, value);
        IF (err != NC_EBADID)
            error("expecting NC_EBADID but got %s",nc_err_code_name(err));
        ELSE_NOK

        canConvert = (var_type[i] == NC_CHAR) == (NCT_ULONGLONG == NCT_TEXT);

        for (j = 0; j < var_rank[i]; j++) {
            start[j] = 0;
            edge[j] = 1;
            stride[j] = 1;
        }

        /* first test when edge[*] > 0 */
        for (j = 0; j < var_rank[i]; j++) {
            if (var_dimid[i][j] == RECDIM) continue; /* skip record dim */
            start[j] = var_shape[i][j];   /* out of boundary check */
            err = nc_put_vars_ulonglong(ncid, i, start, edge, stride, value);
            if (!canConvert) {
                IF (err != NC_ECHAR)
                    error("expecting NC_ECHAR but got %s",nc_err_code_name(err));
                ELSE_NOK
                start[j] = 0;
                continue;
            }
            IF (err != NC_EINVALCOORDS)
                error("expecting NC_EINVALCOORDS but got %s",nc_err_code_name(err));
            ELSE_NOK
            start[j] = 0;
            edge[j] = var_shape[i][j] + 1;
            err = nc_put_vars_ulonglong(ncid, i, start, edge, stride, value);
            IF (err != NC_EEDGE)
                error("expecting NC_EEDGE but got %s",nc_err_code_name(err));
            ELSE_NOK
            edge[j] = 1;
            stride[j] = 0;
            err = nc_put_vars_ulonglong(ncid, i, start, edge, stride, value);
            IF (err != NC_ESTRIDE)
                error("expecting NC_ESTRIDE but got %s",nc_err_code_name(err));
            ELSE_NOK
            stride[j] = 1;
        }
        /* Check correct error returned even when nothing to put */
        for (j = 0; j < var_rank[i]; j++) edge[j] = 0;

        for (j = 0; j < var_rank[i]; j++) {
            if (var_dimid[i][j] == RECDIM) continue; /* skip record dim */
            start[j] = var_shape[i][j];
            err = nc_put_vars_ulonglong(ncid, i, start, edge, stride, value);
            if (!canConvert) {
                IF (err != NC_ECHAR)
                    error("expecting NC_ECHAR but got %s",nc_err_code_name(err));
                ELSE_NOK
                start[j] = 0;
                continue;
            }
#ifdef RELAX_COORD_BOUND
            IF (err != NC_NOERR) /* allowed when edge[j]==0 */
                error("expecting NC_NOERR but got %s",nc_err_code_name(err));
#else
            IF (err != NC_EINVALCOORDS) /* not allowed even when edge[j]==0 */
                error("expecting NC_EINVALCOORDS but got %s",nc_err_code_name(err));
#endif
            ELSE_NOK
            start[j] = var_shape[i][j]+1; /* out of boundary check */
            err = nc_put_vars_ulonglong(ncid, i, start, edge, stride, value);
            IF (err != NC_EINVALCOORDS)
                error("expecting NC_EINVALCOORDS but got %s",nc_err_code_name(err));
            ELSE_NOK
            start[j] = 0;
        }
        for (j = 0; j < var_rank[i]; j++) edge[j] = 1;

        /* Choose a random point dividing each dim into 2 parts */
        /* Put 2^rank (nslabs) slabs so defined */
        nslabs = 1;
        for (j = 0; j < var_rank[i]; j++) {
            mid[j] = roll( var_shape[i][j] );
            nslabs *= 2;
        }
        /* bits of k determine whether to put lower or upper part of dim */
        /* choose random stride from 1 to edge */
        for (k = 0; k < nslabs; k++) {
            nstarts = 1;
            for (j = 0; j < var_rank[i]; j++) {
                if ((k >> j) & 1) {
                    start[j] = 0;
                    edge[j] = mid[j];
                } else {
                    start[j] = mid[j];
                    edge[j] = var_shape[i][j] - mid[j];
                }
                sstride[j] = edge[j] > 0 ? 1+roll(edge[j]) : 1;
                stride[j] = (ptrdiff_t)sstride[j];
                nstarts *= stride[j];
            }
            for (m = 0; m < nstarts; m++) {
                err = toMixedBase(m, var_rank[i], sstride, index);
                IF (err != 0) error("error in toMixedBase");
                nels = 1;
                for (j = 0; j < var_rank[i]; j++) {
                    count[j] = 1 + (edge[j] - index[j] - 1) / (size_t)stride[j];
                    nels *= count[j];
                    index[j] += start[j];
                }
                /* Random choice of forward or backward */
/* TODO
                if ( roll(2) ) {
                    for (j = 0; j < var_rank[i]; j++) {
                        index[j] += (count[j] - 1) * (size_t)stride[j];
                        stride[j] = -stride[j];
                    }
                }
*/
                for (allInExtRange = 1, j = 0; j < nels; j++) {
                    err = toMixedBase(j, var_rank[i], count, index2);
                    IF (err != 0) error("error in toMixedBase");
                    for (d = 0; d < var_rank[i]; d++)
                        index2[d] = index[d] + index2[d] * (size_t)stride[d];
                    value[j] = hash_ulonglong(cdf_format,var_type[i], var_rank[i],
                                       index2, NCT_ULONGLONG);
                    
                        allInExtRange &= inRange3(cdf_format, (double)value[j],
                                                  var_type[i], NCT_ULONGLONG);
                }
                err = nc_put_vars_ulonglong(ncid, i, index, count, stride, value);
                if (canConvert) {
                    if (allInExtRange) {
                        IF (err != NC_NOERR)
                            error("expecting NC_NOERR but got %s",nc_err_code_name(err));
                        ELSE_NOK
                    }
                    
                    else {

                        IF (err != NC_ERANGE)
                            error("expecting NC_ERANGE but got %s",nc_err_code_name(err));
                        ELSE_NOK
                    }


                } else {
                    IF (err != NC_ECHAR)
                        error("expecting NC_ECHAR but got %s",nc_err_code_name(err));
                    ELSE_NOK
                }
            }
        }
    }

    err =  nc_close(ncid);
    IF (err != NC_NOERR)
        error("close: %s",  nc_strerror(err));

    nok += check_vars_ulonglong(scratch, numVars);

    err = nc_delete(scratch);
    IF (err != NC_NOERR)
        error("delete file %s failed", scratch);
    return nok;
}




int
test_nc_put_varm_text(void)
{
    int i, k, d, err, nslabs, ncid, cdf_format, nok=0;
    int canConvert;     /* Both text or both numeric */
    int allInExtRange;  /* all values within external range? */
    size_t j, m, nels;
    size_t start[MAX_RANK], edge[MAX_RANK], index[MAX_RANK];
    size_t index2[MAX_RANK], mid[MAX_RANK], count[MAX_RANK];
    size_t sstride[MAX_RANK];
    ptrdiff_t nstarts;   /* number of different starts */
    ptrdiff_t stride[MAX_RANK], imap[MAX_RANK];
    text value[MAX_NELS];

    err = file_create(scratch, NC_CLOBBER, &ncid);
    IF (err != NC_NOERR) {
        error("create: %s",  nc_strerror(err));
        return nok;
    }

    err =  nc_inq_format(ncid, &cdf_format);
    IF (err != NC_NOERR)
        error("inq_format: %s",  nc_strerror(err));

    def_dims(ncid);
    def_vars(ncid);

    err =  nc_enddef(ncid);
    IF (err != NC_NOERR)
        error("enddef: %s",  nc_strerror(err));

    /* check if can detect a bad file ID */
    err = nc_put_varm_text(BAD_ID, 0, NULL, NULL, NULL, NULL, NULL);
    IF (err != NC_EBADID)
        error("expecting NC_EBADID but got %s",nc_err_code_name(err));
    ELSE_NOK

    /* check if can detect a bad variable ID */
    err = nc_put_varm_text(ncid, BAD_VARID, NULL, NULL, NULL, NULL, NULL);
    IF (err != NC_ENOTVAR)
        error("expecting NC_ENOTVAR but got %s",nc_err_code_name(err));
    ELSE_NOK

    for (i = 0; i < numVars; i++) {
        assert(var_rank[i] <= MAX_RANK);
        assert(var_nels[i] <= MAX_NELS);

        value[0] = 5; /* reset to a value within bounds */

        /* check if can detect a bad file ID */
        err = nc_put_varm_text(BAD_ID, i, NULL, NULL, NULL, NULL, value);
        IF (err != NC_EBADID)
            error("expecting NC_EBADID but got %s",nc_err_code_name(err));
        ELSE_NOK

        canConvert = (var_type[i] == NC_CHAR) ;

        for (j = 0; j < var_rank[i]; j++) {
            start[j] = 0;
            edge[j] = 1;
            stride[j] = 1;
            imap[j] = 1;
        }


        /* first test when edge[*] > 0 */
        for (j = 0; j < var_rank[i]; j++) {
            if (var_dimid[i][j] == RECDIM) continue; /* skip record dim */
            start[j] = var_shape[i][j];   /* out of boundary check */
            err = nc_put_varm_text(ncid, i, start, edge, stride, imap, value);
            if (!canConvert) {
                IF (err != NC_ECHAR)
                    error("expecting NC_ECHAR but got %s",nc_err_code_name(err));
                ELSE_NOK
                start[j] = 0;
                continue;
            }
            IF (err != NC_EINVALCOORDS)
                error("expecting NC_EINVALCOORDS but got %s",nc_err_code_name(err));
            ELSE_NOK
            start[j] = 0;
            edge[j] = var_shape[i][j] + 1;
            err = nc_put_varm_text(ncid, i, start, edge, stride, imap, value);
            IF (err != NC_EEDGE)
                error("expecting NC_EEDGE but got %s",nc_err_code_name(err));
            ELSE_NOK
            edge[j] = 1;
            stride[j] = 0;
            err = nc_put_varm_text(ncid, i, start, edge, stride, imap, value);
            IF (err != NC_ESTRIDE)
                error("expecting NC_ESTRIDE but got %s",nc_err_code_name(err));
            ELSE_NOK
            stride[j] = 1;
        }
        /* Check correct error returned when nothing to put, i.e. edge[*]==0 */
        for (j = 0; j < var_rank[i]; j++) edge[j] = 0;

        for (j = 0; j < var_rank[i]; j++) {
            if (var_dimid[i][j] == RECDIM) continue; /* skip record dim */
            start[j] = var_shape[i][j];
            err = nc_put_varm_text(ncid, i, start, edge, stride, imap, value);
            if (!canConvert) {
                IF (err != NC_ECHAR)
                    error("expecting NC_ECHAR but got %s",nc_err_code_name(err));
                ELSE_NOK
                start[j] = 0;
                continue;
            }
#ifdef RELAX_COORD_BOUND
            IF (err != NC_NOERR) /* allowed when edge[j]==0 */
                error("expecting NC_NOERR but got %s",nc_err_code_name(err));
#else
            IF (err != NC_EINVALCOORDS) /* not allowed even when edge[j]==0 */
                error("expecting NC_EINVALCOORDS but got %s",nc_err_code_name(err));
#endif
            ELSE_NOK
            start[j] = var_shape[i][j]+1; /* out of boundary check */
            err = nc_put_varm_text(ncid, i, start, edge, stride, imap, value);
            IF (err != NC_EINVALCOORDS)
                error("expecting NC_EINVALCOORDS but got %s",nc_err_code_name(err));
            ELSE_NOK
            start[j] = 0;
        }
        for (j = 0; j < var_rank[i]; j++) edge[j] = 1;

        /* Choose a random point dividing each dim into 2 parts */
        /* Put 2^rank (nslabs) slabs so defined */
        nslabs = 1;
        for (j = 0; j < var_rank[i]; j++) {
            mid[j] = roll( var_shape[i][j] );
            nslabs *= 2;
        }
        /* bits of k determine whether to put lower or upper part of dim */
        /* choose random stride from 1 to edge */
        for (k = 0; k < nslabs; k++) {
            nstarts = 1;
            for (j = 0; j < var_rank[i]; j++) {
                if ((k >> j) & 1) {
                    start[j] = 0;
                    edge[j] = mid[j];
                } else {
                    start[j] = mid[j];
                    edge[j] = var_shape[i][j] - mid[j];
                }
                sstride[j] = edge[j] > 0 ? 1+roll(edge[j]) : 1;
                stride[j] = (ptrdiff_t)sstride[j];
                nstarts *= stride[j];
            }
            for (m = 0; m < nstarts; m++) {
                err = toMixedBase(m, var_rank[i], sstride, index);
                IF (err != 0) error("error in toMixedBase");
                nels = 1;
                for (j = 0; j < var_rank[i]; j++) {
                    count[j] = 1 + (edge[j] - index[j] - 1) / (size_t)stride[j];
                    nels *= count[j];
                    index[j] += start[j];
                }
                /* Random choice of forward or backward */
/* TODO
                if ( roll(2) ) {
                    for (j = 0; j < var_rank[i]; j++) {
                        index[j] += (count[j] - 1) * (size_t)stride[j];
                        stride[j] = -stride[j];
                    }
                }
*/
                if (var_rank[i] > 0) {
                    int jj = var_rank[i] - 1;
                    imap[jj] = 1;
                    for (; jj > 0; jj--)
                        imap[jj-1] = imap[jj] * (ptrdiff_t)count[jj];
                }
                for (allInExtRange = 1, j = 0; j < nels; j++) {
                    err = toMixedBase(j, var_rank[i], count, index2);
                    IF (err != 0) error("error in toMixedBase");
                    for (d = 0; d < var_rank[i]; d++)
                        index2[d] = index[d] + index2[d] * (size_t)stride[d];
                    value[j] = hash_text(cdf_format,var_type[i], var_rank[i],
                                       index2, NCT_TEXT);
                    if (var_type[i] != NC_CHAR)
                        allInExtRange &= inRange3(cdf_format, (double)value[j],
                                                  var_type[i], NCT_TEXT);
                }
                err = nc_put_varm_text(ncid,i,index,count,stride,imap,value);
                if (canConvert) {
                    if (allInExtRange) {
                        IF (err != NC_NOERR)
                            error("expecting NC_NOERR but got %s",nc_err_code_name(err));
                        ELSE_NOK
                    }
                    
                    else {

                        IF (err != NC_ERANGE)
                            error("expecting NC_ERANGE but got %s",nc_err_code_name(err));
                        ELSE_NOK
                    }


                } else {
                    IF (err != NC_ECHAR)
                        error("expecting NC_ECHAR but got %s",nc_err_code_name(err));
                    ELSE_NOK
                }
            }
        }
    }

    err =  nc_close(ncid);
    IF (err != NC_NOERR)
        error("close: %s",  nc_strerror(err));

    nok += check_vars_text(scratch, numVars);

    err = nc_delete(scratch);
    IF (err != NC_NOERR)
        error("delete file %s failed", scratch);
    return nok;
}

int
test_nc_put_varm_uchar(void)
{
    int i, k, d, err, nslabs, ncid, cdf_format, nok=0;
    int canConvert;     /* Both text or both numeric */
    int allInExtRange;  /* all values within external range? */
    size_t j, m, nels;
    size_t start[MAX_RANK], edge[MAX_RANK], index[MAX_RANK];
    size_t index2[MAX_RANK], mid[MAX_RANK], count[MAX_RANK];
    size_t sstride[MAX_RANK];
    ptrdiff_t nstarts;   /* number of different starts */
    ptrdiff_t stride[MAX_RANK], imap[MAX_RANK];
    uchar value[MAX_NELS];

    err = file_create(scratch, NC_CLOBBER, &ncid);
    IF (err != NC_NOERR) {
        error("create: %s",  nc_strerror(err));
        return nok;
    }

    err =  nc_inq_format(ncid, &cdf_format);
    IF (err != NC_NOERR)
        error("inq_format: %s",  nc_strerror(err));

    def_dims(ncid);
    def_vars(ncid);

    err =  nc_enddef(ncid);
    IF (err != NC_NOERR)
        error("enddef: %s",  nc_strerror(err));

    /* check if can detect a bad file ID */
    err = nc_put_varm_uchar(BAD_ID, 0, NULL, NULL, NULL, NULL, NULL);
    IF (err != NC_EBADID)
        error("expecting NC_EBADID but got %s",nc_err_code_name(err));
    ELSE_NOK

    /* check if can detect a bad variable ID */
    err = nc_put_varm_uchar(ncid, BAD_VARID, NULL, NULL, NULL, NULL, NULL);
    IF (err != NC_ENOTVAR)
        error("expecting NC_ENOTVAR but got %s",nc_err_code_name(err));
    ELSE_NOK

    for (i = 0; i < numVars; i++) {
        assert(var_rank[i] <= MAX_RANK);
        assert(var_nels[i] <= MAX_NELS);

        value[0] = 5; /* reset to a value within bounds */

        /* check if can detect a bad file ID */
        err = nc_put_varm_uchar(BAD_ID, i, NULL, NULL, NULL, NULL, value);
        IF (err != NC_EBADID)
            error("expecting NC_EBADID but got %s",nc_err_code_name(err));
        ELSE_NOK

        canConvert = (var_type[i] == NC_CHAR) == (NCT_UCHAR == NCT_TEXT);

        for (j = 0; j < var_rank[i]; j++) {
            start[j] = 0;
            edge[j] = 1;
            stride[j] = 1;
            imap[j] = 1;
        }


        /* first test when edge[*] > 0 */
        for (j = 0; j < var_rank[i]; j++) {
            if (var_dimid[i][j] == RECDIM) continue; /* skip record dim */
            start[j] = var_shape[i][j];   /* out of boundary check */
            err = nc_put_varm_uchar(ncid, i, start, edge, stride, imap, value);
            if (!canConvert) {
                IF (err != NC_ECHAR)
                    error("expecting NC_ECHAR but got %s",nc_err_code_name(err));
                ELSE_NOK
                start[j] = 0;
                continue;
            }
            IF (err != NC_EINVALCOORDS)
                error("expecting NC_EINVALCOORDS but got %s",nc_err_code_name(err));
            ELSE_NOK
            start[j] = 0;
            edge[j] = var_shape[i][j] + 1;
            err = nc_put_varm_uchar(ncid, i, start, edge, stride, imap, value);
            IF (err != NC_EEDGE)
                error("expecting NC_EEDGE but got %s",nc_err_code_name(err));
            ELSE_NOK
            edge[j] = 1;
            stride[j] = 0;
            err = nc_put_varm_uchar(ncid, i, start, edge, stride, imap, value);
            IF (err != NC_ESTRIDE)
                error("expecting NC_ESTRIDE but got %s",nc_err_code_name(err));
            ELSE_NOK
            stride[j] = 1;
        }
        /* Check correct error returned when nothing to put, i.e. edge[*]==0 */
        for (j = 0; j < var_rank[i]; j++) edge[j] = 0;

        for (j = 0; j < var_rank[i]; j++) {
            if (var_dimid[i][j] == RECDIM) continue; /* skip record dim */
            start[j] = var_shape[i][j];
            err = nc_put_varm_uchar(ncid, i, start, edge, stride, imap, value);
            if (!canConvert) {
                IF (err != NC_ECHAR)
                    error("expecting NC_ECHAR but got %s",nc_err_code_name(err));
                ELSE_NOK
                start[j] = 0;
                continue;
            }
#ifdef RELAX_COORD_BOUND
            IF (err != NC_NOERR) /* allowed when edge[j]==0 */
                error("expecting NC_NOERR but got %s",nc_err_code_name(err));
#else
            IF (err != NC_EINVALCOORDS) /* not allowed even when edge[j]==0 */
                error("expecting NC_EINVALCOORDS but got %s",nc_err_code_name(err));
#endif
            ELSE_NOK
            start[j] = var_shape[i][j]+1; /* out of boundary check */
            err = nc_put_varm_uchar(ncid, i, start, edge, stride, imap, value);
            IF (err != NC_EINVALCOORDS)
                error("expecting NC_EINVALCOORDS but got %s",nc_err_code_name(err));
            ELSE_NOK
            start[j] = 0;
        }
        for (j = 0; j < var_rank[i]; j++) edge[j] = 1;

        /* Choose a random point dividing each dim into 2 parts */
        /* Put 2^rank (nslabs) slabs so defined */
        nslabs = 1;
        for (j = 0; j < var_rank[i]; j++) {
            mid[j] = roll( var_shape[i][j] );
            nslabs *= 2;
        }
        /* bits of k determine whether to put lower or upper part of dim */
        /* choose random stride from 1 to edge */
        for (k = 0; k < nslabs; k++) {
            nstarts = 1;
            for (j = 0; j < var_rank[i]; j++) {
                if ((k >> j) & 1) {
                    start[j] = 0;
                    edge[j] = mid[j];
                } else {
                    start[j] = mid[j];
                    edge[j] = var_shape[i][j] - mid[j];
                }
                sstride[j] = edge[j] > 0 ? 1+roll(edge[j]) : 1;
                stride[j] = (ptrdiff_t)sstride[j];
                nstarts *= stride[j];
            }
            for (m = 0; m < nstarts; m++) {
                err = toMixedBase(m, var_rank[i], sstride, index);
                IF (err != 0) error("error in toMixedBase");
                nels = 1;
                for (j = 0; j < var_rank[i]; j++) {
                    count[j] = 1 + (edge[j] - index[j] - 1) / (size_t)stride[j];
                    nels *= count[j];
                    index[j] += start[j];
                }
                /* Random choice of forward or backward */
/* TODO
                if ( roll(2) ) {
                    for (j = 0; j < var_rank[i]; j++) {
                        index[j] += (count[j] - 1) * (size_t)stride[j];
                        stride[j] = -stride[j];
                    }
                }
*/
                if (var_rank[i] > 0) {
                    int jj = var_rank[i] - 1;
                    imap[jj] = 1;
                    for (; jj > 0; jj--)
                        imap[jj-1] = imap[jj] * (ptrdiff_t)count[jj];
                }
                for (allInExtRange = 1, j = 0; j < nels; j++) {
                    err = toMixedBase(j, var_rank[i], count, index2);
                    IF (err != 0) error("error in toMixedBase");
                    for (d = 0; d < var_rank[i]; d++)
                        index2[d] = index[d] + index2[d] * (size_t)stride[d];
                    value[j] = hash_uchar(cdf_format,var_type[i], var_rank[i],
                                       index2, NCT_UCHAR);
                    
                        allInExtRange &= inRange3(cdf_format, (double)value[j],
                                                  var_type[i], NCT_UCHAR);
                }
                err = nc_put_varm_uchar(ncid,i,index,count,stride,imap,value);
                if (canConvert) {
                    if (allInExtRange) {
                        IF (err != NC_NOERR)
                            error("expecting NC_NOERR but got %s",nc_err_code_name(err));
                        ELSE_NOK
                    }
                    
#if !defined(USE_PNETCDF) || (PNETCDF_VERSION_MAJOR==1 && PNETCDF_VERSION_MINOR>=8)
                    else {

                        IF (err != NC_ERANGE)
                            error("expecting NC_ERANGE but got %s",nc_err_code_name(err));
                        ELSE_NOK
                    }
#endif

                } else {
                    IF (err != NC_ECHAR)
                        error("expecting NC_ECHAR but got %s",nc_err_code_name(err));
                    ELSE_NOK
                }
            }
        }
    }

    err =  nc_close(ncid);
    IF (err != NC_NOERR)
        error("close: %s",  nc_strerror(err));

    nok += check_vars_uchar(scratch, numVars);

    err = nc_delete(scratch);
    IF (err != NC_NOERR)
        error("delete file %s failed", scratch);
    return nok;
}

int
test_nc_put_varm_schar(void)
{
    int i, k, d, err, nslabs, ncid, cdf_format, nok=0;
    int canConvert;     /* Both text or both numeric */
    int allInExtRange;  /* all values within external range? */
    size_t j, m, nels;
    size_t start[MAX_RANK], edge[MAX_RANK], index[MAX_RANK];
    size_t index2[MAX_RANK], mid[MAX_RANK], count[MAX_RANK];
    size_t sstride[MAX_RANK];
    ptrdiff_t nstarts;   /* number of different starts */
    ptrdiff_t stride[MAX_RANK], imap[MAX_RANK];
    schar value[MAX_NELS];

    err = file_create(scratch, NC_CLOBBER, &ncid);
    IF (err != NC_NOERR) {
        error("create: %s",  nc_strerror(err));
        return nok;
    }

    err =  nc_inq_format(ncid, &cdf_format);
    IF (err != NC_NOERR)
        error("inq_format: %s",  nc_strerror(err));

    def_dims(ncid);
    def_vars(ncid);

    err =  nc_enddef(ncid);
    IF (err != NC_NOERR)
        error("enddef: %s",  nc_strerror(err));

    /* check if can detect a bad file ID */
    err = nc_put_varm_schar(BAD_ID, 0, NULL, NULL, NULL, NULL, NULL);
    IF (err != NC_EBADID)
        error("expecting NC_EBADID but got %s",nc_err_code_name(err));
    ELSE_NOK

    /* check if can detect a bad variable ID */
    err = nc_put_varm_schar(ncid, BAD_VARID, NULL, NULL, NULL, NULL, NULL);
    IF (err != NC_ENOTVAR)
        error("expecting NC_ENOTVAR but got %s",nc_err_code_name(err));
    ELSE_NOK

    for (i = 0; i < numVars; i++) {
        assert(var_rank[i] <= MAX_RANK);
        assert(var_nels[i] <= MAX_NELS);

        value[0] = 5; /* reset to a value within bounds */

        /* check if can detect a bad file ID */
        err = nc_put_varm_schar(BAD_ID, i, NULL, NULL, NULL, NULL, value);
        IF (err != NC_EBADID)
            error("expecting NC_EBADID but got %s",nc_err_code_name(err));
        ELSE_NOK

        canConvert = (var_type[i] == NC_CHAR) == (NCT_SCHAR == NCT_TEXT);

        for (j = 0; j < var_rank[i]; j++) {
            start[j] = 0;
            edge[j] = 1;
            stride[j] = 1;
            imap[j] = 1;
        }


        /* first test when edge[*] > 0 */
        for (j = 0; j < var_rank[i]; j++) {
            if (var_dimid[i][j] == RECDIM) continue; /* skip record dim */
            start[j] = var_shape[i][j];   /* out of boundary check */
            err = nc_put_varm_schar(ncid, i, start, edge, stride, imap, value);
            if (!canConvert) {
                IF (err != NC_ECHAR)
                    error("expecting NC_ECHAR but got %s",nc_err_code_name(err));
                ELSE_NOK
                start[j] = 0;
                continue;
            }
            IF (err != NC_EINVALCOORDS)
                error("expecting NC_EINVALCOORDS but got %s",nc_err_code_name(err));
            ELSE_NOK
            start[j] = 0;
            edge[j] = var_shape[i][j] + 1;
            err = nc_put_varm_schar(ncid, i, start, edge, stride, imap, value);
            IF (err != NC_EEDGE)
                error("expecting NC_EEDGE but got %s",nc_err_code_name(err));
            ELSE_NOK
            edge[j] = 1;
            stride[j] = 0;
            err = nc_put_varm_schar(ncid, i, start, edge, stride, imap, value);
            IF (err != NC_ESTRIDE)
                error("expecting NC_ESTRIDE but got %s",nc_err_code_name(err));
            ELSE_NOK
            stride[j] = 1;
        }
        /* Check correct error returned when nothing to put, i.e. edge[*]==0 */
        for (j = 0; j < var_rank[i]; j++) edge[j] = 0;

        for (j = 0; j < var_rank[i]; j++) {
            if (var_dimid[i][j] == RECDIM) continue; /* skip record dim */
            start[j] = var_shape[i][j];
            err = nc_put_varm_schar(ncid, i, start, edge, stride, imap, value);
            if (!canConvert) {
                IF (err != NC_ECHAR)
                    error("expecting NC_ECHAR but got %s",nc_err_code_name(err));
                ELSE_NOK
                start[j] = 0;
                continue;
            }
#ifdef RELAX_COORD_BOUND
            IF (err != NC_NOERR) /* allowed when edge[j]==0 */
                error("expecting NC_NOERR but got %s",nc_err_code_name(err));
#else
            IF (err != NC_EINVALCOORDS) /* not allowed even when edge[j]==0 */
                error("expecting NC_EINVALCOORDS but got %s",nc_err_code_name(err));
#endif
            ELSE_NOK
            start[j] = var_shape[i][j]+1; /* out of boundary check */
            err = nc_put_varm_schar(ncid, i, start, edge, stride, imap, value);
            IF (err != NC_EINVALCOORDS)
                error("expecting NC_EINVALCOORDS but got %s",nc_err_code_name(err));
            ELSE_NOK
            start[j] = 0;
        }
        for (j = 0; j < var_rank[i]; j++) edge[j] = 1;

        /* Choose a random point dividing each dim into 2 parts */
        /* Put 2^rank (nslabs) slabs so defined */
        nslabs = 1;
        for (j = 0; j < var_rank[i]; j++) {
            mid[j] = roll( var_shape[i][j] );
            nslabs *= 2;
        }
        /* bits of k determine whether to put lower or upper part of dim */
        /* choose random stride from 1 to edge */
        for (k = 0; k < nslabs; k++) {
            nstarts = 1;
            for (j = 0; j < var_rank[i]; j++) {
                if ((k >> j) & 1) {
                    start[j] = 0;
                    edge[j] = mid[j];
                } else {
                    start[j] = mid[j];
                    edge[j] = var_shape[i][j] - mid[j];
                }
                sstride[j] = edge[j] > 0 ? 1+roll(edge[j]) : 1;
                stride[j] = (ptrdiff_t)sstride[j];
                nstarts *= stride[j];
            }
            for (m = 0; m < nstarts; m++) {
                err = toMixedBase(m, var_rank[i], sstride, index);
                IF (err != 0) error("error in toMixedBase");
                nels = 1;
                for (j = 0; j < var_rank[i]; j++) {
                    count[j] = 1 + (edge[j] - index[j] - 1) / (size_t)stride[j];
                    nels *= count[j];
                    index[j] += start[j];
                }
                /* Random choice of forward or backward */
/* TODO
                if ( roll(2) ) {
                    for (j = 0; j < var_rank[i]; j++) {
                        index[j] += (count[j] - 1) * (size_t)stride[j];
                        stride[j] = -stride[j];
                    }
                }
*/
                if (var_rank[i] > 0) {
                    int jj = var_rank[i] - 1;
                    imap[jj] = 1;
                    for (; jj > 0; jj--)
                        imap[jj-1] = imap[jj] * (ptrdiff_t)count[jj];
                }
                for (allInExtRange = 1, j = 0; j < nels; j++) {
                    err = toMixedBase(j, var_rank[i], count, index2);
                    IF (err != 0) error("error in toMixedBase");
                    for (d = 0; d < var_rank[i]; d++)
                        index2[d] = index[d] + index2[d] * (size_t)stride[d];
                    value[j] = hash_schar(cdf_format,var_type[i], var_rank[i],
                                       index2, NCT_SCHAR);
                    
                        allInExtRange &= inRange3(cdf_format, (double)value[j],
                                                  var_type[i], NCT_SCHAR);
                }
                err = nc_put_varm_schar(ncid,i,index,count,stride,imap,value);
                if (canConvert) {
                    if (allInExtRange) {
                        IF (err != NC_NOERR)
                            error("expecting NC_NOERR but got %s",nc_err_code_name(err));
                        ELSE_NOK
                    }
                    
#if defined(USE_PNETCDF) && PNETCDF_VERSION_MAJOR==1 && PNETCDF_VERSION_MINOR<7
                    else if (cdf_format < NC_FORMAT_CDF5) {
#else
                    else {
#endif
                        IF (err != NC_ERANGE)
                            error("expecting NC_ERANGE but got %s",nc_err_code_name(err));
                        ELSE_NOK
                    }


                } else {
                    IF (err != NC_ECHAR)
                        error("expecting NC_ECHAR but got %s",nc_err_code_name(err));
                    ELSE_NOK
                }
            }
        }
    }

    err =  nc_close(ncid);
    IF (err != NC_NOERR)
        error("close: %s",  nc_strerror(err));

    nok += check_vars_schar(scratch, numVars);

    err = nc_delete(scratch);
    IF (err != NC_NOERR)
        error("delete file %s failed", scratch);
    return nok;
}

int
test_nc_put_varm_short(void)
{
    int i, k, d, err, nslabs, ncid, cdf_format, nok=0;
    int canConvert;     /* Both text or both numeric */
    int allInExtRange;  /* all values within external range? */
    size_t j, m, nels;
    size_t start[MAX_RANK], edge[MAX_RANK], index[MAX_RANK];
    size_t index2[MAX_RANK], mid[MAX_RANK], count[MAX_RANK];
    size_t sstride[MAX_RANK];
    ptrdiff_t nstarts;   /* number of different starts */
    ptrdiff_t stride[MAX_RANK], imap[MAX_RANK];
    short value[MAX_NELS];

    err = file_create(scratch, NC_CLOBBER, &ncid);
    IF (err != NC_NOERR) {
        error("create: %s",  nc_strerror(err));
        return nok;
    }

    err =  nc_inq_format(ncid, &cdf_format);
    IF (err != NC_NOERR)
        error("inq_format: %s",  nc_strerror(err));

    def_dims(ncid);
    def_vars(ncid);

    err =  nc_enddef(ncid);
    IF (err != NC_NOERR)
        error("enddef: %s",  nc_strerror(err));

    /* check if can detect a bad file ID */
    err = nc_put_varm_short(BAD_ID, 0, NULL, NULL, NULL, NULL, NULL);
    IF (err != NC_EBADID)
        error("expecting NC_EBADID but got %s",nc_err_code_name(err));
    ELSE_NOK

    /* check if can detect a bad variable ID */
    err = nc_put_varm_short(ncid, BAD_VARID, NULL, NULL, NULL, NULL, NULL);
    IF (err != NC_ENOTVAR)
        error("expecting NC_ENOTVAR but got %s",nc_err_code_name(err));
    ELSE_NOK

    for (i = 0; i < numVars; i++) {
        assert(var_rank[i] <= MAX_RANK);
        assert(var_nels[i] <= MAX_NELS);

        value[0] = 5; /* reset to a value within bounds */

        /* check if can detect a bad file ID */
        err = nc_put_varm_short(BAD_ID, i, NULL, NULL, NULL, NULL, value);
        IF (err != NC_EBADID)
            error("expecting NC_EBADID but got %s",nc_err_code_name(err));
        ELSE_NOK

        canConvert = (var_type[i] == NC_CHAR) == (NCT_SHORT == NCT_TEXT);

        for (j = 0; j < var_rank[i]; j++) {
            start[j] = 0;
            edge[j] = 1;
            stride[j] = 1;
            imap[j] = 1;
        }


        /* first test when edge[*] > 0 */
        for (j = 0; j < var_rank[i]; j++) {
            if (var_dimid[i][j] == RECDIM) continue; /* skip record dim */
            start[j] = var_shape[i][j];   /* out of boundary check */
            err = nc_put_varm_short(ncid, i, start, edge, stride, imap, value);
            if (!canConvert) {
                IF (err != NC_ECHAR)
                    error("expecting NC_ECHAR but got %s",nc_err_code_name(err));
                ELSE_NOK
                start[j] = 0;
                continue;
            }
            IF (err != NC_EINVALCOORDS)
                error("expecting NC_EINVALCOORDS but got %s",nc_err_code_name(err));
            ELSE_NOK
            start[j] = 0;
            edge[j] = var_shape[i][j] + 1;
            err = nc_put_varm_short(ncid, i, start, edge, stride, imap, value);
            IF (err != NC_EEDGE)
                error("expecting NC_EEDGE but got %s",nc_err_code_name(err));
            ELSE_NOK
            edge[j] = 1;
            stride[j] = 0;
            err = nc_put_varm_short(ncid, i, start, edge, stride, imap, value);
            IF (err != NC_ESTRIDE)
                error("expecting NC_ESTRIDE but got %s",nc_err_code_name(err));
            ELSE_NOK
            stride[j] = 1;
        }
        /* Check correct error returned when nothing to put, i.e. edge[*]==0 */
        for (j = 0; j < var_rank[i]; j++) edge[j] = 0;

        for (j = 0; j < var_rank[i]; j++) {
            if (var_dimid[i][j] == RECDIM) continue; /* skip record dim */
            start[j] = var_shape[i][j];
            err = nc_put_varm_short(ncid, i, start, edge, stride, imap, value);
            if (!canConvert) {
                IF (err != NC_ECHAR)
                    error("expecting NC_ECHAR but got %s",nc_err_code_name(err));
                ELSE_NOK
                start[j] = 0;
                continue;
            }
#ifdef RELAX_COORD_BOUND
            IF (err != NC_NOERR) /* allowed when edge[j]==0 */
                error("expecting NC_NOERR but got %s",nc_err_code_name(err));
#else
            IF (err != NC_EINVALCOORDS) /* not allowed even when edge[j]==0 */
                error("expecting NC_EINVALCOORDS but got %s",nc_err_code_name(err));
#endif
            ELSE_NOK
            start[j] = var_shape[i][j]+1; /* out of boundary check */
            err = nc_put_varm_short(ncid, i, start, edge, stride, imap, value);
            IF (err != NC_EINVALCOORDS)
                error("expecting NC_EINVALCOORDS but got %s",nc_err_code_name(err));
            ELSE_NOK
            start[j] = 0;
        }
        for (j = 0; j < var_rank[i]; j++) edge[j] = 1;

        /* Choose a random point dividing each dim into 2 parts */
        /* Put 2^rank (nslabs) slabs so defined */
        nslabs = 1;
        for (j = 0; j < var_rank[i]; j++) {
            mid[j] = roll( var_shape[i][j] );
            nslabs *= 2;
        }
        /* bits of k determine whether to put lower or upper part of dim */
        /* choose random stride from 1 to edge */
        for (k = 0; k < nslabs; k++) {
            nstarts = 1;
            for (j = 0; j < var_rank[i]; j++) {
                if ((k >> j) & 1) {
                    start[j] = 0;
                    edge[j] = mid[j];
                } else {
                    start[j] = mid[j];
                    edge[j] = var_shape[i][j] - mid[j];
                }
                sstride[j] = edge[j] > 0 ? 1+roll(edge[j]) : 1;
                stride[j] = (ptrdiff_t)sstride[j];
                nstarts *= stride[j];
            }
            for (m = 0; m < nstarts; m++) {
                err = toMixedBase(m, var_rank[i], sstride, index);
                IF (err != 0) error("error in toMixedBase");
                nels = 1;
                for (j = 0; j < var_rank[i]; j++) {
                    count[j] = 1 + (edge[j] - index[j] - 1) / (size_t)stride[j];
                    nels *= count[j];
                    index[j] += start[j];
                }
                /* Random choice of forward or backward */
/* TODO
                if ( roll(2) ) {
                    for (j = 0; j < var_rank[i]; j++) {
                        index[j] += (count[j] - 1) * (size_t)stride[j];
                        stride[j] = -stride[j];
                    }
                }
*/
                if (var_rank[i] > 0) {
                    int jj = var_rank[i] - 1;
                    imap[jj] = 1;
                    for (; jj > 0; jj--)
                        imap[jj-1] = imap[jj] * (ptrdiff_t)count[jj];
                }
                for (allInExtRange = 1, j = 0; j < nels; j++) {
                    err = toMixedBase(j, var_rank[i], count, index2);
                    IF (err != 0) error("error in toMixedBase");
                    for (d = 0; d < var_rank[i]; d++)
                        index2[d] = index[d] + index2[d] * (size_t)stride[d];
                    value[j] = hash_short(cdf_format,var_type[i], var_rank[i],
                                       index2, NCT_SHORT);
                    
                        allInExtRange &= inRange3(cdf_format, (double)value[j],
                                                  var_type[i], NCT_SHORT);
                }
                err = nc_put_varm_short(ncid,i,index,count,stride,imap,value);
                if (canConvert) {
                    if (allInExtRange) {
                        IF (err != NC_NOERR)
                            error("expecting NC_NOERR but got %s",nc_err_code_name(err));
                        ELSE_NOK
                    }
                    
                    else {

                        IF (err != NC_ERANGE)
                            error("expecting NC_ERANGE but got %s",nc_err_code_name(err));
                        ELSE_NOK
                    }


                } else {
                    IF (err != NC_ECHAR)
                        error("expecting NC_ECHAR but got %s",nc_err_code_name(err));
                    ELSE_NOK
                }
            }
        }
    }

    err =  nc_close(ncid);
    IF (err != NC_NOERR)
        error("close: %s",  nc_strerror(err));

    nok += check_vars_short(scratch, numVars);

    err = nc_delete(scratch);
    IF (err != NC_NOERR)
        error("delete file %s failed", scratch);
    return nok;
}

int
test_nc_put_varm_int(void)
{
    int i, k, d, err, nslabs, ncid, cdf_format, nok=0;
    int canConvert;     /* Both text or both numeric */
    int allInExtRange;  /* all values within external range? */
    size_t j, m, nels;
    size_t start[MAX_RANK], edge[MAX_RANK], index[MAX_RANK];
    size_t index2[MAX_RANK], mid[MAX_RANK], count[MAX_RANK];
    size_t sstride[MAX_RANK];
    ptrdiff_t nstarts;   /* number of different starts */
    ptrdiff_t stride[MAX_RANK], imap[MAX_RANK];
    int value[MAX_NELS];

    err = file_create(scratch, NC_CLOBBER, &ncid);
    IF (err != NC_NOERR) {
        error("create: %s",  nc_strerror(err));
        return nok;
    }

    err =  nc_inq_format(ncid, &cdf_format);
    IF (err != NC_NOERR)
        error("inq_format: %s",  nc_strerror(err));

    def_dims(ncid);
    def_vars(ncid);

    err =  nc_enddef(ncid);
    IF (err != NC_NOERR)
        error("enddef: %s",  nc_strerror(err));

    /* check if can detect a bad file ID */
    err = nc_put_varm_int(BAD_ID, 0, NULL, NULL, NULL, NULL, NULL);
    IF (err != NC_EBADID)
        error("expecting NC_EBADID but got %s",nc_err_code_name(err));
    ELSE_NOK

    /* check if can detect a bad variable ID */
    err = nc_put_varm_int(ncid, BAD_VARID, NULL, NULL, NULL, NULL, NULL);
    IF (err != NC_ENOTVAR)
        error("expecting NC_ENOTVAR but got %s",nc_err_code_name(err));
    ELSE_NOK

    for (i = 0; i < numVars; i++) {
        assert(var_rank[i] <= MAX_RANK);
        assert(var_nels[i] <= MAX_NELS);

        value[0] = 5; /* reset to a value within bounds */

        /* check if can detect a bad file ID */
        err = nc_put_varm_int(BAD_ID, i, NULL, NULL, NULL, NULL, value);
        IF (err != NC_EBADID)
            error("expecting NC_EBADID but got %s",nc_err_code_name(err));
        ELSE_NOK

        canConvert = (var_type[i] == NC_CHAR) == (NCT_INT == NCT_TEXT);

        for (j = 0; j < var_rank[i]; j++) {
            start[j] = 0;
            edge[j] = 1;
            stride[j] = 1;
            imap[j] = 1;
        }


        /* first test when edge[*] > 0 */
        for (j = 0; j < var_rank[i]; j++) {
            if (var_dimid[i][j] == RECDIM) continue; /* skip record dim */
            start[j] = var_shape[i][j];   /* out of boundary check */
            err = nc_put_varm_int(ncid, i, start, edge, stride, imap, value);
            if (!canConvert) {
                IF (err != NC_ECHAR)
                    error("expecting NC_ECHAR but got %s",nc_err_code_name(err));
                ELSE_NOK
                start[j] = 0;
                continue;
            }
            IF (err != NC_EINVALCOORDS)
                error("expecting NC_EINVALCOORDS but got %s",nc_err_code_name(err));
            ELSE_NOK
            start[j] = 0;
            edge[j] = var_shape[i][j] + 1;
            err = nc_put_varm_int(ncid, i, start, edge, stride, imap, value);
            IF (err != NC_EEDGE)
                error("expecting NC_EEDGE but got %s",nc_err_code_name(err));
            ELSE_NOK
            edge[j] = 1;
            stride[j] = 0;
            err = nc_put_varm_int(ncid, i, start, edge, stride, imap, value);
            IF (err != NC_ESTRIDE)
                error("expecting NC_ESTRIDE but got %s",nc_err_code_name(err));
            ELSE_NOK
            stride[j] = 1;
        }
        /* Check correct error returned when nothing to put, i.e. edge[*]==0 */
        for (j = 0; j < var_rank[i]; j++) edge[j] = 0;

        for (j = 0; j < var_rank[i]; j++) {
            if (var_dimid[i][j] == RECDIM) continue; /* skip record dim */
            start[j] = var_shape[i][j];
            err = nc_put_varm_int(ncid, i, start, edge, stride, imap, value);
            if (!canConvert) {
                IF (err != NC_ECHAR)
                    error("expecting NC_ECHAR but got %s",nc_err_code_name(err));
                ELSE_NOK
                start[j] = 0;
                continue;
            }
#ifdef RELAX_COORD_BOUND
            IF (err != NC_NOERR) /* allowed when edge[j]==0 */
                error("expecting NC_NOERR but got %s",nc_err_code_name(err));
#else
            IF (err != NC_EINVALCOORDS) /* not allowed even when edge[j]==0 */
                error("expecting NC_EINVALCOORDS but got %s",nc_err_code_name(err));
#endif
            ELSE_NOK
            start[j] = var_shape[i][j]+1; /* out of boundary check */
            err = nc_put_varm_int(ncid, i, start, edge, stride, imap, value);
            IF (err != NC_EINVALCOORDS)
                error("expecting NC_EINVALCOORDS but got %s",nc_err_code_name(err));
            ELSE_NOK
            start[j] = 0;
        }
        for (j = 0; j < var_rank[i]; j++) edge[j] = 1;

        /* Choose a random point dividing each dim into 2 parts */
        /* Put 2^rank (nslabs) slabs so defined */
        nslabs = 1;
        for (j = 0; j < var_rank[i]; j++) {
            mid[j] = roll( var_shape[i][j] );
            nslabs *= 2;
        }
        /* bits of k determine whether to put lower or upper part of dim */
        /* choose random stride from 1 to edge */
        for (k = 0; k < nslabs; k++) {
            nstarts = 1;
            for (j = 0; j < var_rank[i]; j++) {
                if ((k >> j) & 1) {
                    start[j] = 0;
                    edge[j] = mid[j];
                } else {
                    start[j] = mid[j];
                    edge[j] = var_shape[i][j] - mid[j];
                }
                sstride[j] = edge[j] > 0 ? 1+roll(edge[j]) : 1;
                stride[j] = (ptrdiff_t)sstride[j];
                nstarts *= stride[j];
            }
            for (m = 0; m < nstarts; m++) {
                err = toMixedBase(m, var_rank[i], sstride, index);
                IF (err != 0) error("error in toMixedBase");
                nels = 1;
                for (j = 0; j < var_rank[i]; j++) {
                    count[j] = 1 + (edge[j] - index[j] - 1) / (size_t)stride[j];
                    nels *= count[j];
                    index[j] += start[j];
                }
                /* Random choice of forward or backward */
/* TODO
                if ( roll(2) ) {
                    for (j = 0; j < var_rank[i]; j++) {
                        index[j] += (count[j] - 1) * (size_t)stride[j];
                        stride[j] = -stride[j];
                    }
                }
*/
                if (var_rank[i] > 0) {
                    int jj = var_rank[i] - 1;
                    imap[jj] = 1;
                    for (; jj > 0; jj--)
                        imap[jj-1] = imap[jj] * (ptrdiff_t)count[jj];
                }
                for (allInExtRange = 1, j = 0; j < nels; j++) {
                    err = toMixedBase(j, var_rank[i], count, index2);
                    IF (err != 0) error("error in toMixedBase");
                    for (d = 0; d < var_rank[i]; d++)
                        index2[d] = index[d] + index2[d] * (size_t)stride[d];
                    value[j] = hash_int(cdf_format,var_type[i], var_rank[i],
                                       index2, NCT_INT);
                    
                        allInExtRange &= inRange3(cdf_format, (double)value[j],
                                                  var_type[i], NCT_INT);
                }
                err = nc_put_varm_int(ncid,i,index,count,stride,imap,value);
                if (canConvert) {
                    if (allInExtRange) {
                        IF (err != NC_NOERR)
                            error("expecting NC_NOERR but got %s",nc_err_code_name(err));
                        ELSE_NOK
                    }
                    
                    else {

                        IF (err != NC_ERANGE)
                            error("expecting NC_ERANGE but got %s",nc_err_code_name(err));
                        ELSE_NOK
                    }


                } else {
                    IF (err != NC_ECHAR)
                        error("expecting NC_ECHAR but got %s",nc_err_code_name(err));
                    ELSE_NOK
                }
            }
        }
    }

    err =  nc_close(ncid);
    IF (err != NC_NOERR)
        error("close: %s",  nc_strerror(err));

    nok += check_vars_int(scratch, numVars);

    err = nc_delete(scratch);
    IF (err != NC_NOERR)
        error("delete file %s failed", scratch);
    return nok;
}

int
test_nc_put_varm_long(void)
{
    int i, k, d, err, nslabs, ncid, cdf_format, nok=0;
    int canConvert;     /* Both text or both numeric */
    int allInExtRange;  /* all values within external range? */
    size_t j, m, nels;
    size_t start[MAX_RANK], edge[MAX_RANK], index[MAX_RANK];
    size_t index2[MAX_RANK], mid[MAX_RANK], count[MAX_RANK];
    size_t sstride[MAX_RANK];
    ptrdiff_t nstarts;   /* number of different starts */
    ptrdiff_t stride[MAX_RANK], imap[MAX_RANK];
    long value[MAX_NELS];

    err = file_create(scratch, NC_CLOBBER, &ncid);
    IF (err != NC_NOERR) {
        error("create: %s",  nc_strerror(err));
        return nok;
    }

    err =  nc_inq_format(ncid, &cdf_format);
    IF (err != NC_NOERR)
        error("inq_format: %s",  nc_strerror(err));

    def_dims(ncid);
    def_vars(ncid);

    err =  nc_enddef(ncid);
    IF (err != NC_NOERR)
        error("enddef: %s",  nc_strerror(err));

    /* check if can detect a bad file ID */
    err = nc_put_varm_long(BAD_ID, 0, NULL, NULL, NULL, NULL, NULL);
    IF (err != NC_EBADID)
        error("expecting NC_EBADID but got %s",nc_err_code_name(err));
    ELSE_NOK

    /* check if can detect a bad variable ID */
    err = nc_put_varm_long(ncid, BAD_VARID, NULL, NULL, NULL, NULL, NULL);
    IF (err != NC_ENOTVAR)
        error("expecting NC_ENOTVAR but got %s",nc_err_code_name(err));
    ELSE_NOK

    for (i = 0; i < numVars; i++) {
        assert(var_rank[i] <= MAX_RANK);
        assert(var_nels[i] <= MAX_NELS);

        value[0] = 5; /* reset to a value within bounds */

        /* check if can detect a bad file ID */
        err = nc_put_varm_long(BAD_ID, i, NULL, NULL, NULL, NULL, value);
        IF (err != NC_EBADID)
            error("expecting NC_EBADID but got %s",nc_err_code_name(err));
        ELSE_NOK

        canConvert = (var_type[i] == NC_CHAR) == (NCT_LONG == NCT_TEXT);

        for (j = 0; j < var_rank[i]; j++) {
            start[j] = 0;
            edge[j] = 1;
            stride[j] = 1;
            imap[j] = 1;
        }


        /* first test when edge[*] > 0 */
        for (j = 0; j < var_rank[i]; j++) {
            if (var_dimid[i][j] == RECDIM) continue; /* skip record dim */
            start[j] = var_shape[i][j];   /* out of boundary check */
            err = nc_put_varm_long(ncid, i, start, edge, stride, imap, value);
            if (!canConvert) {
                IF (err != NC_ECHAR)
                    error("expecting NC_ECHAR but got %s",nc_err_code_name(err));
                ELSE_NOK
                start[j] = 0;
                continue;
            }
            IF (err != NC_EINVALCOORDS)
                error("expecting NC_EINVALCOORDS but got %s",nc_err_code_name(err));
            ELSE_NOK
            start[j] = 0;
            edge[j] = var_shape[i][j] + 1;
            err = nc_put_varm_long(ncid, i, start, edge, stride, imap, value);
            IF (err != NC_EEDGE)
                error("expecting NC_EEDGE but got %s",nc_err_code_name(err));
            ELSE_NOK
            edge[j] = 1;
            stride[j] = 0;
            err = nc_put_varm_long(ncid, i, start, edge, stride, imap, value);
            IF (err != NC_ESTRIDE)
                error("expecting NC_ESTRIDE but got %s",nc_err_code_name(err));
            ELSE_NOK
            stride[j] = 1;
        }
        /* Check correct error returned when nothing to put, i.e. edge[*]==0 */
        for (j = 0; j < var_rank[i]; j++) edge[j] = 0;

        for (j = 0; j < var_rank[i]; j++) {
            if (var_dimid[i][j] == RECDIM) continue; /* skip record dim */
            start[j] = var_shape[i][j];
            err = nc_put_varm_long(ncid, i, start, edge, stride, imap, value);
            if (!canConvert) {
                IF (err != NC_ECHAR)
                    error("expecting NC_ECHAR but got %s",nc_err_code_name(err));
                ELSE_NOK
                start[j] = 0;
                continue;
            }
#ifdef RELAX_COORD_BOUND
            IF (err != NC_NOERR) /* allowed when edge[j]==0 */
                error("expecting NC_NOERR but got %s",nc_err_code_name(err));
#else
            IF (err != NC_EINVALCOORDS) /* not allowed even when edge[j]==0 */
                error("expecting NC_EINVALCOORDS but got %s",nc_err_code_name(err));
#endif
            ELSE_NOK
            start[j] = var_shape[i][j]+1; /* out of boundary check */
            err = nc_put_varm_long(ncid, i, start, edge, stride, imap, value);
            IF (err != NC_EINVALCOORDS)
                error("expecting NC_EINVALCOORDS but got %s",nc_err_code_name(err));
            ELSE_NOK
            start[j] = 0;
        }
        for (j = 0; j < var_rank[i]; j++) edge[j] = 1;

        /* Choose a random point dividing each dim into 2 parts */
        /* Put 2^rank (nslabs) slabs so defined */
        nslabs = 1;
        for (j = 0; j < var_rank[i]; j++) {
            mid[j] = roll( var_shape[i][j] );
            nslabs *= 2;
        }
        /* bits of k determine whether to put lower or upper part of dim */
        /* choose random stride from 1 to edge */
        for (k = 0; k < nslabs; k++) {
            nstarts = 1;
            for (j = 0; j < var_rank[i]; j++) {
                if ((k >> j) & 1) {
                    start[j] = 0;
                    edge[j] = mid[j];
                } else {
                    start[j] = mid[j];
                    edge[j] = var_shape[i][j] - mid[j];
                }
                sstride[j] = edge[j] > 0 ? 1+roll(edge[j]) : 1;
                stride[j] = (ptrdiff_t)sstride[j];
                nstarts *= stride[j];
            }
            for (m = 0; m < nstarts; m++) {
                err = toMixedBase(m, var_rank[i], sstride, index);
                IF (err != 0) error("error in toMixedBase");
                nels = 1;
                for (j = 0; j < var_rank[i]; j++) {
                    count[j] = 1 + (edge[j] - index[j] - 1) / (size_t)stride[j];
                    nels *= count[j];
                    index[j] += start[j];
                }
                /* Random choice of forward or backward */
/* TODO
                if ( roll(2) ) {
                    for (j = 0; j < var_rank[i]; j++) {
                        index[j] += (count[j] - 1) * (size_t)stride[j];
                        stride[j] = -stride[j];
                    }
                }
*/
                if (var_rank[i] > 0) {
                    int jj = var_rank[i] - 1;
                    imap[jj] = 1;
                    for (; jj > 0; jj--)
                        imap[jj-1] = imap[jj] * (ptrdiff_t)count[jj];
                }
                for (allInExtRange = 1, j = 0; j < nels; j++) {
                    err = toMixedBase(j, var_rank[i], count, index2);
                    IF (err != 0) error("error in toMixedBase");
                    for (d = 0; d < var_rank[i]; d++)
                        index2[d] = index[d] + index2[d] * (size_t)stride[d];
                    value[j] = hash_long(cdf_format,var_type[i], var_rank[i],
                                       index2, NCT_LONG);
                    
                        allInExtRange &= inRange3(cdf_format, (double)value[j],
                                                  var_type[i], NCT_LONG);
                }
                err = nc_put_varm_long(ncid,i,index,count,stride,imap,value);
                if (canConvert) {
                    if (allInExtRange) {
                        IF (err != NC_NOERR)
                            error("expecting NC_NOERR but got %s",nc_err_code_name(err));
                        ELSE_NOK
                    }
                    
                    else {

                        IF (err != NC_ERANGE)
                            error("expecting NC_ERANGE but got %s",nc_err_code_name(err));
                        ELSE_NOK
                    }


                } else {
                    IF (err != NC_ECHAR)
                        error("expecting NC_ECHAR but got %s",nc_err_code_name(err));
                    ELSE_NOK
                }
            }
        }
    }

    err =  nc_close(ncid);
    IF (err != NC_NOERR)
        error("close: %s",  nc_strerror(err));

    nok += check_vars_long(scratch, numVars);

    err = nc_delete(scratch);
    IF (err != NC_NOERR)
        error("delete file %s failed", scratch);
    return nok;
}

int
test_nc_put_varm_float(void)
{
    int i, k, d, err, nslabs, ncid, cdf_format, nok=0;
    int canConvert;     /* Both text or both numeric */
    int allInExtRange;  /* all values within external range? */
    size_t j, m, nels;
    size_t start[MAX_RANK], edge[MAX_RANK], index[MAX_RANK];
    size_t index2[MAX_RANK], mid[MAX_RANK], count[MAX_RANK];
    size_t sstride[MAX_RANK];
    ptrdiff_t nstarts;   /* number of different starts */
    ptrdiff_t stride[MAX_RANK], imap[MAX_RANK];
    float value[MAX_NELS];

    err = file_create(scratch, NC_CLOBBER, &ncid);
    IF (err != NC_NOERR) {
        error("create: %s",  nc_strerror(err));
        return nok;
    }

    err =  nc_inq_format(ncid, &cdf_format);
    IF (err != NC_NOERR)
        error("inq_format: %s",  nc_strerror(err));

    def_dims(ncid);
    def_vars(ncid);

    err =  nc_enddef(ncid);
    IF (err != NC_NOERR)
        error("enddef: %s",  nc_strerror(err));

    /* check if can detect a bad file ID */
    err = nc_put_varm_float(BAD_ID, 0, NULL, NULL, NULL, NULL, NULL);
    IF (err != NC_EBADID)
        error("expecting NC_EBADID but got %s",nc_err_code_name(err));
    ELSE_NOK

    /* check if can detect a bad variable ID */
    err = nc_put_varm_float(ncid, BAD_VARID, NULL, NULL, NULL, NULL, NULL);
    IF (err != NC_ENOTVAR)
        error("expecting NC_ENOTVAR but got %s",nc_err_code_name(err));
    ELSE_NOK

    for (i = 0; i < numVars; i++) {
        assert(var_rank[i] <= MAX_RANK);
        assert(var_nels[i] <= MAX_NELS);

        value[0] = 5; /* reset to a value within bounds */

        /* check if can detect a bad file ID */
        err = nc_put_varm_float(BAD_ID, i, NULL, NULL, NULL, NULL, value);
        IF (err != NC_EBADID)
            error("expecting NC_EBADID but got %s",nc_err_code_name(err));
        ELSE_NOK

        canConvert = (var_type[i] == NC_CHAR) == (NCT_FLOAT == NCT_TEXT);

        for (j = 0; j < var_rank[i]; j++) {
            start[j] = 0;
            edge[j] = 1;
            stride[j] = 1;
            imap[j] = 1;
        }


        /* first test when edge[*] > 0 */
        for (j = 0; j < var_rank[i]; j++) {
            if (var_dimid[i][j] == RECDIM) continue; /* skip record dim */
            start[j] = var_shape[i][j];   /* out of boundary check */
            err = nc_put_varm_float(ncid, i, start, edge, stride, imap, value);
            if (!canConvert) {
                IF (err != NC_ECHAR)
                    error("expecting NC_ECHAR but got %s",nc_err_code_name(err));
                ELSE_NOK
                start[j] = 0;
                continue;
            }
            IF (err != NC_EINVALCOORDS)
                error("expecting NC_EINVALCOORDS but got %s",nc_err_code_name(err));
            ELSE_NOK
            start[j] = 0;
            edge[j] = var_shape[i][j] + 1;
            err = nc_put_varm_float(ncid, i, start, edge, stride, imap, value);
            IF (err != NC_EEDGE)
                error("expecting NC_EEDGE but got %s",nc_err_code_name(err));
            ELSE_NOK
            edge[j] = 1;
            stride[j] = 0;
            err = nc_put_varm_float(ncid, i, start, edge, stride, imap, value);
            IF (err != NC_ESTRIDE)
                error("expecting NC_ESTRIDE but got %s",nc_err_code_name(err));
            ELSE_NOK
            stride[j] = 1;
        }
        /* Check correct error returned when nothing to put, i.e. edge[*]==0 */
        for (j = 0; j < var_rank[i]; j++) edge[j] = 0;

        for (j = 0; j < var_rank[i]; j++) {
            if (var_dimid[i][j] == RECDIM) continue; /* skip record dim */
            start[j] = var_shape[i][j];
            err = nc_put_varm_float(ncid, i, start, edge, stride, imap, value);
            if (!canConvert) {
                IF (err != NC_ECHAR)
                    error("expecting NC_ECHAR but got %s",nc_err_code_name(err));
                ELSE_NOK
                start[j] = 0;
                continue;
            }
#ifdef RELAX_COORD_BOUND
            IF (err != NC_NOERR) /* allowed when edge[j]==0 */
                error("expecting NC_NOERR but got %s",nc_err_code_name(err));
#else
            IF (err != NC_EINVALCOORDS) /* not allowed even when edge[j]==0 */
                error("expecting NC_EINVALCOORDS but got %s",nc_err_code_name(err));
#endif
            ELSE_NOK
            start[j] = var_shape[i][j]+1; /* out of boundary check */
            err = nc_put_varm_float(ncid, i, start, edge, stride, imap, value);
            IF (err != NC_EINVALCOORDS)
                error("expecting NC_EINVALCOORDS but got %s",nc_err_code_name(err));
            ELSE_NOK
            start[j] = 0;
        }
        for (j = 0; j < var_rank[i]; j++) edge[j] = 1;

        /* Choose a random point dividing each dim into 2 parts */
        /* Put 2^rank (nslabs) slabs so defined */
        nslabs = 1;
        for (j = 0; j < var_rank[i]; j++) {
            mid[j] = roll( var_shape[i][j] );
            nslabs *= 2;
        }
        /* bits of k determine whether to put lower or upper part of dim */
        /* choose random stride from 1 to edge */
        for (k = 0; k < nslabs; k++) {
            nstarts = 1;
            for (j = 0; j < var_rank[i]; j++) {
                if ((k >> j) & 1) {
                    start[j] = 0;
                    edge[j] = mid[j];
                } else {
                    start[j] = mid[j];
                    edge[j] = var_shape[i][j] - mid[j];
                }
                sstride[j] = edge[j] > 0 ? 1+roll(edge[j]) : 1;
                stride[j] = (ptrdiff_t)sstride[j];
                nstarts *= stride[j];
            }
            for (m = 0; m < nstarts; m++) {
                err = toMixedBase(m, var_rank[i], sstride, index);
                IF (err != 0) error("error in toMixedBase");
                nels = 1;
                for (j = 0; j < var_rank[i]; j++) {
                    count[j] = 1 + (edge[j] - index[j] - 1) / (size_t)stride[j];
                    nels *= count[j];
                    index[j] += start[j];
                }
                /* Random choice of forward or backward */
/* TODO
                if ( roll(2) ) {
                    for (j = 0; j < var_rank[i]; j++) {
                        index[j] += (count[j] - 1) * (size_t)stride[j];
                        stride[j] = -stride[j];
                    }
                }
*/
                if (var_rank[i] > 0) {
                    int jj = var_rank[i] - 1;
                    imap[jj] = 1;
                    for (; jj > 0; jj--)
                        imap[jj-1] = imap[jj] * (ptrdiff_t)count[jj];
                }
                for (allInExtRange = 1, j = 0; j < nels; j++) {
                    err = toMixedBase(j, var_rank[i], count, index2);
                    IF (err != 0) error("error in toMixedBase");
                    for (d = 0; d < var_rank[i]; d++)
                        index2[d] = index[d] + index2[d] * (size_t)stride[d];
                    value[j] = hash_float(cdf_format,var_type[i], var_rank[i],
                                       index2, NCT_FLOAT);
                    
                        allInExtRange &= inRange3(cdf_format, (double)value[j],
                                                  var_type[i], NCT_FLOAT);
                }
                err = nc_put_varm_float(ncid,i,index,count,stride,imap,value);
                if (canConvert) {
                    if (allInExtRange) {
                        IF (err != NC_NOERR)
                            error("expecting NC_NOERR but got %s",nc_err_code_name(err));
                        ELSE_NOK
                    }
                    
                    else {

                        IF (err != NC_ERANGE)
                            error("expecting NC_ERANGE but got %s",nc_err_code_name(err));
                        ELSE_NOK
                    }


                } else {
                    IF (err != NC_ECHAR)
                        error("expecting NC_ECHAR but got %s",nc_err_code_name(err));
                    ELSE_NOK
                }
            }
        }
    }

    err =  nc_close(ncid);
    IF (err != NC_NOERR)
        error("close: %s",  nc_strerror(err));

    nok += check_vars_float(scratch, numVars);

    err = nc_delete(scratch);
    IF (err != NC_NOERR)
        error("delete file %s failed", scratch);
    return nok;
}

int
test_nc_put_varm_double(void)
{
    int i, k, d, err, nslabs, ncid, cdf_format, nok=0;
    int canConvert;     /* Both text or both numeric */
    int allInExtRange;  /* all values within external range? */
    size_t j, m, nels;
    size_t start[MAX_RANK], edge[MAX_RANK], index[MAX_RANK];
    size_t index2[MAX_RANK], mid[MAX_RANK], count[MAX_RANK];
    size_t sstride[MAX_RANK];
    ptrdiff_t nstarts;   /* number of different starts */
    ptrdiff_t stride[MAX_RANK], imap[MAX_RANK];
    double value[MAX_NELS];

    err = file_create(scratch, NC_CLOBBER, &ncid);
    IF (err != NC_NOERR) {
        error("create: %s",  nc_strerror(err));
        return nok;
    }

    err =  nc_inq_format(ncid, &cdf_format);
    IF (err != NC_NOERR)
        error("inq_format: %s",  nc_strerror(err));

    def_dims(ncid);
    def_vars(ncid);

    err =  nc_enddef(ncid);
    IF (err != NC_NOERR)
        error("enddef: %s",  nc_strerror(err));

    /* check if can detect a bad file ID */
    err = nc_put_varm_double(BAD_ID, 0, NULL, NULL, NULL, NULL, NULL);
    IF (err != NC_EBADID)
        error("expecting NC_EBADID but got %s",nc_err_code_name(err));
    ELSE_NOK

    /* check if can detect a bad variable ID */
    err = nc_put_varm_double(ncid, BAD_VARID, NULL, NULL, NULL, NULL, NULL);
    IF (err != NC_ENOTVAR)
        error("expecting NC_ENOTVAR but got %s",nc_err_code_name(err));
    ELSE_NOK

    for (i = 0; i < numVars; i++) {
        assert(var_rank[i] <= MAX_RANK);
        assert(var_nels[i] <= MAX_NELS);

        value[0] = 5; /* reset to a value within bounds */

        /* check if can detect a bad file ID */
        err = nc_put_varm_double(BAD_ID, i, NULL, NULL, NULL, NULL, value);
        IF (err != NC_EBADID)
            error("expecting NC_EBADID but got %s",nc_err_code_name(err));
        ELSE_NOK

        canConvert = (var_type[i] == NC_CHAR) == (NCT_DOUBLE == NCT_TEXT);

        for (j = 0; j < var_rank[i]; j++) {
            start[j] = 0;
            edge[j] = 1;
            stride[j] = 1;
            imap[j] = 1;
        }


        /* first test when edge[*] > 0 */
        for (j = 0; j < var_rank[i]; j++) {
            if (var_dimid[i][j] == RECDIM) continue; /* skip record dim */
            start[j] = var_shape[i][j];   /* out of boundary check */
            err = nc_put_varm_double(ncid, i, start, edge, stride, imap, value);
            if (!canConvert) {
                IF (err != NC_ECHAR)
                    error("expecting NC_ECHAR but got %s",nc_err_code_name(err));
                ELSE_NOK
                start[j] = 0;
                continue;
            }
            IF (err != NC_EINVALCOORDS)
                error("expecting NC_EINVALCOORDS but got %s",nc_err_code_name(err));
            ELSE_NOK
            start[j] = 0;
            edge[j] = var_shape[i][j] + 1;
            err = nc_put_varm_double(ncid, i, start, edge, stride, imap, value);
            IF (err != NC_EEDGE)
                error("expecting NC_EEDGE but got %s",nc_err_code_name(err));
            ELSE_NOK
            edge[j] = 1;
            stride[j] = 0;
            err = nc_put_varm_double(ncid, i, start, edge, stride, imap, value);
            IF (err != NC_ESTRIDE)
                error("expecting NC_ESTRIDE but got %s",nc_err_code_name(err));
            ELSE_NOK
            stride[j] = 1;
        }
        /* Check correct error returned when nothing to put, i.e. edge[*]==0 */
        for (j = 0; j < var_rank[i]; j++) edge[j] = 0;

        for (j = 0; j < var_rank[i]; j++) {
            if (var_dimid[i][j] == RECDIM) continue; /* skip record dim */
            start[j] = var_shape[i][j];
            err = nc_put_varm_double(ncid, i, start, edge, stride, imap, value);
            if (!canConvert) {
                IF (err != NC_ECHAR)
                    error("expecting NC_ECHAR but got %s",nc_err_code_name(err));
                ELSE_NOK
                start[j] = 0;
                continue;
            }
#ifdef RELAX_COORD_BOUND
            IF (err != NC_NOERR) /* allowed when edge[j]==0 */
                error("expecting NC_NOERR but got %s",nc_err_code_name(err));
#else
            IF (err != NC_EINVALCOORDS) /* not allowed even when edge[j]==0 */
                error("expecting NC_EINVALCOORDS but got %s",nc_err_code_name(err));
#endif
            ELSE_NOK
            start[j] = var_shape[i][j]+1; /* out of boundary check */
            err = nc_put_varm_double(ncid, i, start, edge, stride, imap, value);
            IF (err != NC_EINVALCOORDS)
                error("expecting NC_EINVALCOORDS but got %s",nc_err_code_name(err));
            ELSE_NOK
            start[j] = 0;
        }
        for (j = 0; j < var_rank[i]; j++) edge[j] = 1;

        /* Choose a random point dividing each dim into 2 parts */
        /* Put 2^rank (nslabs) slabs so defined */
        nslabs = 1;
        for (j = 0; j < var_rank[i]; j++) {
            mid[j] = roll( var_shape[i][j] );
            nslabs *= 2;
        }
        /* bits of k determine whether to put lower or upper part of dim */
        /* choose random stride from 1 to edge */
        for (k = 0; k < nslabs; k++) {
            nstarts = 1;
            for (j = 0; j < var_rank[i]; j++) {
                if ((k >> j) & 1) {
                    start[j] = 0;
                    edge[j] = mid[j];
                } else {
                    start[j] = mid[j];
                    edge[j] = var_shape[i][j] - mid[j];
                }
                sstride[j] = edge[j] > 0 ? 1+roll(edge[j]) : 1;
                stride[j] = (ptrdiff_t)sstride[j];
                nstarts *= stride[j];
            }
            for (m = 0; m < nstarts; m++) {
                err = toMixedBase(m, var_rank[i], sstride, index);
                IF (err != 0) error("error in toMixedBase");
                nels = 1;
                for (j = 0; j < var_rank[i]; j++) {
                    count[j] = 1 + (edge[j] - index[j] - 1) / (size_t)stride[j];
                    nels *= count[j];
                    index[j] += start[j];
                }
                /* Random choice of forward or backward */
/* TODO
                if ( roll(2) ) {
                    for (j = 0; j < var_rank[i]; j++) {
                        index[j] += (count[j] - 1) * (size_t)stride[j];
                        stride[j] = -stride[j];
                    }
                }
*/
                if (var_rank[i] > 0) {
                    int jj = var_rank[i] - 1;
                    imap[jj] = 1;
                    for (; jj > 0; jj--)
                        imap[jj-1] = imap[jj] * (ptrdiff_t)count[jj];
                }
                for (allInExtRange = 1, j = 0; j < nels; j++) {
                    err = toMixedBase(j, var_rank[i], count, index2);
                    IF (err != 0) error("error in toMixedBase");
                    for (d = 0; d < var_rank[i]; d++)
                        index2[d] = index[d] + index2[d] * (size_t)stride[d];
                    value[j] = hash_double(cdf_format,var_type[i], var_rank[i],
                                       index2, NCT_DOUBLE);
                    
                        allInExtRange &= inRange3(cdf_format, (double)value[j],
                                                  var_type[i], NCT_DOUBLE);
                }
                err = nc_put_varm_double(ncid,i,index,count,stride,imap,value);
                if (canConvert) {
                    if (allInExtRange) {
                        IF (err != NC_NOERR)
                            error("expecting NC_NOERR but got %s",nc_err_code_name(err));
                        ELSE_NOK
                    }
                    
                    else {

                        IF (err != NC_ERANGE)
                            error("expecting NC_ERANGE but got %s",nc_err_code_name(err));
                        ELSE_NOK
                    }


                } else {
                    IF (err != NC_ECHAR)
                        error("expecting NC_ECHAR but got %s",nc_err_code_name(err));
                    ELSE_NOK
                }
            }
        }
    }

    err =  nc_close(ncid);
    IF (err != NC_NOERR)
        error("close: %s",  nc_strerror(err));

    nok += check_vars_double(scratch, numVars);

    err = nc_delete(scratch);
    IF (err != NC_NOERR)
        error("delete file %s failed", scratch);
    return nok;
}

int
test_nc_put_varm_ushort(void)
{
    int i, k, d, err, nslabs, ncid, cdf_format, nok=0;
    int canConvert;     /* Both text or both numeric */
    int allInExtRange;  /* all values within external range? */
    size_t j, m, nels;
    size_t start[MAX_RANK], edge[MAX_RANK], index[MAX_RANK];
    size_t index2[MAX_RANK], mid[MAX_RANK], count[MAX_RANK];
    size_t sstride[MAX_RANK];
    ptrdiff_t nstarts;   /* number of different starts */
    ptrdiff_t stride[MAX_RANK], imap[MAX_RANK];
    ushort value[MAX_NELS];

    err = file_create(scratch, NC_CLOBBER, &ncid);
    IF (err != NC_NOERR) {
        error("create: %s",  nc_strerror(err));
        return nok;
    }

    err =  nc_inq_format(ncid, &cdf_format);
    IF (err != NC_NOERR)
        error("inq_format: %s",  nc_strerror(err));

    def_dims(ncid);
    def_vars(ncid);

    err =  nc_enddef(ncid);
    IF (err != NC_NOERR)
        error("enddef: %s",  nc_strerror(err));

    /* check if can detect a bad file ID */
    err = nc_put_varm_ushort(BAD_ID, 0, NULL, NULL, NULL, NULL, NULL);
    IF (err != NC_EBADID)
        error("expecting NC_EBADID but got %s",nc_err_code_name(err));
    ELSE_NOK

    /* check if can detect a bad variable ID */
    err = nc_put_varm_ushort(ncid, BAD_VARID, NULL, NULL, NULL, NULL, NULL);
    IF (err != NC_ENOTVAR)
        error("expecting NC_ENOTVAR but got %s",nc_err_code_name(err));
    ELSE_NOK

    for (i = 0; i < numVars; i++) {
        assert(var_rank[i] <= MAX_RANK);
        assert(var_nels[i] <= MAX_NELS);

        value[0] = 5; /* reset to a value within bounds */

        /* check if can detect a bad file ID */
        err = nc_put_varm_ushort(BAD_ID, i, NULL, NULL, NULL, NULL, value);
        IF (err != NC_EBADID)
            error("expecting NC_EBADID but got %s",nc_err_code_name(err));
        ELSE_NOK

        canConvert = (var_type[i] == NC_CHAR) == (NCT_USHORT == NCT_TEXT);

        for (j = 0; j < var_rank[i]; j++) {
            start[j] = 0;
            edge[j] = 1;
            stride[j] = 1;
            imap[j] = 1;
        }


        /* first test when edge[*] > 0 */
        for (j = 0; j < var_rank[i]; j++) {
            if (var_dimid[i][j] == RECDIM) continue; /* skip record dim */
            start[j] = var_shape[i][j];   /* out of boundary check */
            err = nc_put_varm_ushort(ncid, i, start, edge, stride, imap, value);
            if (!canConvert) {
                IF (err != NC_ECHAR)
                    error("expecting NC_ECHAR but got %s",nc_err_code_name(err));
                ELSE_NOK
                start[j] = 0;
                continue;
            }
            IF (err != NC_EINVALCOORDS)
                error("expecting NC_EINVALCOORDS but got %s",nc_err_code_name(err));
            ELSE_NOK
            start[j] = 0;
            edge[j] = var_shape[i][j] + 1;
            err = nc_put_varm_ushort(ncid, i, start, edge, stride, imap, value);
            IF (err != NC_EEDGE)
                error("expecting NC_EEDGE but got %s",nc_err_code_name(err));
            ELSE_NOK
            edge[j] = 1;
            stride[j] = 0;
            err = nc_put_varm_ushort(ncid, i, start, edge, stride, imap, value);
            IF (err != NC_ESTRIDE)
                error("expecting NC_ESTRIDE but got %s",nc_err_code_name(err));
            ELSE_NOK
            stride[j] = 1;
        }
        /* Check correct error returned when nothing to put, i.e. edge[*]==0 */
        for (j = 0; j < var_rank[i]; j++) edge[j] = 0;

        for (j = 0; j < var_rank[i]; j++) {
            if (var_dimid[i][j] == RECDIM) continue; /* skip record dim */
            start[j] = var_shape[i][j];
            err = nc_put_varm_ushort(ncid, i, start, edge, stride, imap, value);
            if (!canConvert) {
                IF (err != NC_ECHAR)
                    error("expecting NC_ECHAR but got %s",nc_err_code_name(err));
                ELSE_NOK
                start[j] = 0;
                continue;
            }
#ifdef RELAX_COORD_BOUND
            IF (err != NC_NOERR) /* allowed when edge[j]==0 */
                error("expecting NC_NOERR but got %s",nc_err_code_name(err));
#else
            IF (err != NC_EINVALCOORDS) /* not allowed even when edge[j]==0 */
                error("expecting NC_EINVALCOORDS but got %s",nc_err_code_name(err));
#endif
            ELSE_NOK
            start[j] = var_shape[i][j]+1; /* out of boundary check */
            err = nc_put_varm_ushort(ncid, i, start, edge, stride, imap, value);
            IF (err != NC_EINVALCOORDS)
                error("expecting NC_EINVALCOORDS but got %s",nc_err_code_name(err));
            ELSE_NOK
            start[j] = 0;
        }
        for (j = 0; j < var_rank[i]; j++) edge[j] = 1;

        /* Choose a random point dividing each dim into 2 parts */
        /* Put 2^rank (nslabs) slabs so defined */
        nslabs = 1;
        for (j = 0; j < var_rank[i]; j++) {
            mid[j] = roll( var_shape[i][j] );
            nslabs *= 2;
        }
        /* bits of k determine whether to put lower or upper part of dim */
        /* choose random stride from 1 to edge */
        for (k = 0; k < nslabs; k++) {
            nstarts = 1;
            for (j = 0; j < var_rank[i]; j++) {
                if ((k >> j) & 1) {
                    start[j] = 0;
                    edge[j] = mid[j];
                } else {
                    start[j] = mid[j];
                    edge[j] = var_shape[i][j] - mid[j];
                }
                sstride[j] = edge[j] > 0 ? 1+roll(edge[j]) : 1;
                stride[j] = (ptrdiff_t)sstride[j];
                nstarts *= stride[j];
            }
            for (m = 0; m < nstarts; m++) {
                err = toMixedBase(m, var_rank[i], sstride, index);
                IF (err != 0) error("error in toMixedBase");
                nels = 1;
                for (j = 0; j < var_rank[i]; j++) {
                    count[j] = 1 + (edge[j] - index[j] - 1) / (size_t)stride[j];
                    nels *= count[j];
                    index[j] += start[j];
                }
                /* Random choice of forward or backward */
/* TODO
                if ( roll(2) ) {
                    for (j = 0; j < var_rank[i]; j++) {
                        index[j] += (count[j] - 1) * (size_t)stride[j];
                        stride[j] = -stride[j];
                    }
                }
*/
                if (var_rank[i] > 0) {
                    int jj = var_rank[i] - 1;
                    imap[jj] = 1;
                    for (; jj > 0; jj--)
                        imap[jj-1] = imap[jj] * (ptrdiff_t)count[jj];
                }
                for (allInExtRange = 1, j = 0; j < nels; j++) {
                    err = toMixedBase(j, var_rank[i], count, index2);
                    IF (err != 0) error("error in toMixedBase");
                    for (d = 0; d < var_rank[i]; d++)
                        index2[d] = index[d] + index2[d] * (size_t)stride[d];
                    value[j] = hash_ushort(cdf_format,var_type[i], var_rank[i],
                                       index2, NCT_USHORT);
                    
                        allInExtRange &= inRange3(cdf_format, (double)value[j],
                                                  var_type[i], NCT_USHORT);
                }
                err = nc_put_varm_ushort(ncid,i,index,count,stride,imap,value);
                if (canConvert) {
                    if (allInExtRange) {
                        IF (err != NC_NOERR)
                            error("expecting NC_NOERR but got %s",nc_err_code_name(err));
                        ELSE_NOK
                    }
                    
                    else {

                        IF (err != NC_ERANGE)
                            error("expecting NC_ERANGE but got %s",nc_err_code_name(err));
                        ELSE_NOK
                    }


                } else {
                    IF (err != NC_ECHAR)
                        error("expecting NC_ECHAR but got %s",nc_err_code_name(err));
                    ELSE_NOK
                }
            }
        }
    }

    err =  nc_close(ncid);
    IF (err != NC_NOERR)
        error("close: %s",  nc_strerror(err));

    nok += check_vars_ushort(scratch, numVars);

    err = nc_delete(scratch);
    IF (err != NC_NOERR)
        error("delete file %s failed", scratch);
    return nok;
}

int
test_nc_put_varm_uint(void)
{
    int i, k, d, err, nslabs, ncid, cdf_format, nok=0;
    int canConvert;     /* Both text or both numeric */
    int allInExtRange;  /* all values within external range? */
    size_t j, m, nels;
    size_t start[MAX_RANK], edge[MAX_RANK], index[MAX_RANK];
    size_t index2[MAX_RANK], mid[MAX_RANK], count[MAX_RANK];
    size_t sstride[MAX_RANK];
    ptrdiff_t nstarts;   /* number of different starts */
    ptrdiff_t stride[MAX_RANK], imap[MAX_RANK];
    uint value[MAX_NELS];

    err = file_create(scratch, NC_CLOBBER, &ncid);
    IF (err != NC_NOERR) {
        error("create: %s",  nc_strerror(err));
        return nok;
    }

    err =  nc_inq_format(ncid, &cdf_format);
    IF (err != NC_NOERR)
        error("inq_format: %s",  nc_strerror(err));

    def_dims(ncid);
    def_vars(ncid);

    err =  nc_enddef(ncid);
    IF (err != NC_NOERR)
        error("enddef: %s",  nc_strerror(err));

    /* check if can detect a bad file ID */
    err = nc_put_varm_uint(BAD_ID, 0, NULL, NULL, NULL, NULL, NULL);
    IF (err != NC_EBADID)
        error("expecting NC_EBADID but got %s",nc_err_code_name(err));
    ELSE_NOK

    /* check if can detect a bad variable ID */
    err = nc_put_varm_uint(ncid, BAD_VARID, NULL, NULL, NULL, NULL, NULL);
    IF (err != NC_ENOTVAR)
        error("expecting NC_ENOTVAR but got %s",nc_err_code_name(err));
    ELSE_NOK

    for (i = 0; i < numVars; i++) {
        assert(var_rank[i] <= MAX_RANK);
        assert(var_nels[i] <= MAX_NELS);

        value[0] = 5; /* reset to a value within bounds */

        /* check if can detect a bad file ID */
        err = nc_put_varm_uint(BAD_ID, i, NULL, NULL, NULL, NULL, value);
        IF (err != NC_EBADID)
            error("expecting NC_EBADID but got %s",nc_err_code_name(err));
        ELSE_NOK

        canConvert = (var_type[i] == NC_CHAR) == (NCT_UINT == NCT_TEXT);

        for (j = 0; j < var_rank[i]; j++) {
            start[j] = 0;
            edge[j] = 1;
            stride[j] = 1;
            imap[j] = 1;
        }


        /* first test when edge[*] > 0 */
        for (j = 0; j < var_rank[i]; j++) {
            if (var_dimid[i][j] == RECDIM) continue; /* skip record dim */
            start[j] = var_shape[i][j];   /* out of boundary check */
            err = nc_put_varm_uint(ncid, i, start, edge, stride, imap, value);
            if (!canConvert) {
                IF (err != NC_ECHAR)
                    error("expecting NC_ECHAR but got %s",nc_err_code_name(err));
                ELSE_NOK
                start[j] = 0;
                continue;
            }
            IF (err != NC_EINVALCOORDS)
                error("expecting NC_EINVALCOORDS but got %s",nc_err_code_name(err));
            ELSE_NOK
            start[j] = 0;
            edge[j] = var_shape[i][j] + 1;
            err = nc_put_varm_uint(ncid, i, start, edge, stride, imap, value);
            IF (err != NC_EEDGE)
                error("expecting NC_EEDGE but got %s",nc_err_code_name(err));
            ELSE_NOK
            edge[j] = 1;
            stride[j] = 0;
            err = nc_put_varm_uint(ncid, i, start, edge, stride, imap, value);
            IF (err != NC_ESTRIDE)
                error("expecting NC_ESTRIDE but got %s",nc_err_code_name(err));
            ELSE_NOK
            stride[j] = 1;
        }
        /* Check correct error returned when nothing to put, i.e. edge[*]==0 */
        for (j = 0; j < var_rank[i]; j++) edge[j] = 0;

        for (j = 0; j < var_rank[i]; j++) {
            if (var_dimid[i][j] == RECDIM) continue; /* skip record dim */
            start[j] = var_shape[i][j];
            err = nc_put_varm_uint(ncid, i, start, edge, stride, imap, value);
            if (!canConvert) {
                IF (err != NC_ECHAR)
                    error("expecting NC_ECHAR but got %s",nc_err_code_name(err));
                ELSE_NOK
                start[j] = 0;
                continue;
            }
#ifdef RELAX_COORD_BOUND
            IF (err != NC_NOERR) /* allowed when edge[j]==0 */
                error("expecting NC_NOERR but got %s",nc_err_code_name(err));
#else
            IF (err != NC_EINVALCOORDS) /* not allowed even when edge[j]==0 */
                error("expecting NC_EINVALCOORDS but got %s",nc_err_code_name(err));
#endif
            ELSE_NOK
            start[j] = var_shape[i][j]+1; /* out of boundary check */
            err = nc_put_varm_uint(ncid, i, start, edge, stride, imap, value);
            IF (err != NC_EINVALCOORDS)
                error("expecting NC_EINVALCOORDS but got %s",nc_err_code_name(err));
            ELSE_NOK
            start[j] = 0;
        }
        for (j = 0; j < var_rank[i]; j++) edge[j] = 1;

        /* Choose a random point dividing each dim into 2 parts */
        /* Put 2^rank (nslabs) slabs so defined */
        nslabs = 1;
        for (j = 0; j < var_rank[i]; j++) {
            mid[j] = roll( var_shape[i][j] );
            nslabs *= 2;
        }
        /* bits of k determine whether to put lower or upper part of dim */
        /* choose random stride from 1 to edge */
        for (k = 0; k < nslabs; k++) {
            nstarts = 1;
            for (j = 0; j < var_rank[i]; j++) {
                if ((k >> j) & 1) {
                    start[j] = 0;
                    edge[j] = mid[j];
                } else {
                    start[j] = mid[j];
                    edge[j] = var_shape[i][j] - mid[j];
                }
                sstride[j] = edge[j] > 0 ? 1+roll(edge[j]) : 1;
                stride[j] = (ptrdiff_t)sstride[j];
                nstarts *= stride[j];
            }
            for (m = 0; m < nstarts; m++) {
                err = toMixedBase(m, var_rank[i], sstride, index);
                IF (err != 0) error("error in toMixedBase");
                nels = 1;
                for (j = 0; j < var_rank[i]; j++) {
                    count[j] = 1 + (edge[j] - index[j] - 1) / (size_t)stride[j];
                    nels *= count[j];
                    index[j] += start[j];
                }
                /* Random choice of forward or backward */
/* TODO
                if ( roll(2) ) {
                    for (j = 0; j < var_rank[i]; j++) {
                        index[j] += (count[j] - 1) * (size_t)stride[j];
                        stride[j] = -stride[j];
                    }
                }
*/
                if (var_rank[i] > 0) {
                    int jj = var_rank[i] - 1;
                    imap[jj] = 1;
                    for (; jj > 0; jj--)
                        imap[jj-1] = imap[jj] * (ptrdiff_t)count[jj];
                }
                for (allInExtRange = 1, j = 0; j < nels; j++) {
                    err = toMixedBase(j, var_rank[i], count, index2);
                    IF (err != 0) error("error in toMixedBase");
                    for (d = 0; d < var_rank[i]; d++)
                        index2[d] = index[d] + index2[d] * (size_t)stride[d];
                    value[j] = hash_uint(cdf_format,var_type[i], var_rank[i],
                                       index2, NCT_UINT);
                    
                        allInExtRange &= inRange3(cdf_format, (double)value[j],
                                                  var_type[i], NCT_UINT);
                }
                err = nc_put_varm_uint(ncid,i,index,count,stride,imap,value);
                if (canConvert) {
                    if (allInExtRange) {
                        IF (err != NC_NOERR)
                            error("expecting NC_NOERR but got %s",nc_err_code_name(err));
                        ELSE_NOK
                    }
                    
                    else {

                        IF (err != NC_ERANGE)
                            error("expecting NC_ERANGE but got %s",nc_err_code_name(err));
                        ELSE_NOK
                    }


                } else {
                    IF (err != NC_ECHAR)
                        error("expecting NC_ECHAR but got %s",nc_err_code_name(err));
                    ELSE_NOK
                }
            }
        }
    }

    err =  nc_close(ncid);
    IF (err != NC_NOERR)
        error("close: %s",  nc_strerror(err));

    nok += check_vars_uint(scratch, numVars);

    err = nc_delete(scratch);
    IF (err != NC_NOERR)
        error("delete file %s failed", scratch);
    return nok;
}

int
test_nc_put_varm_longlong(void)
{
    int i, k, d, err, nslabs, ncid, cdf_format, nok=0;
    int canConvert;     /* Both text or both numeric */
    int allInExtRange;  /* all values within external range? */
    size_t j, m, nels;
    size_t start[MAX_RANK], edge[MAX_RANK], index[MAX_RANK];
    size_t index2[MAX_RANK], mid[MAX_RANK], count[MAX_RANK];
    size_t sstride[MAX_RANK];
    ptrdiff_t nstarts;   /* number of different starts */
    ptrdiff_t stride[MAX_RANK], imap[MAX_RANK];
    longlong value[MAX_NELS];

    err = file_create(scratch, NC_CLOBBER, &ncid);
    IF (err != NC_NOERR) {
        error("create: %s",  nc_strerror(err));
        return nok;
    }

    err =  nc_inq_format(ncid, &cdf_format);
    IF (err != NC_NOERR)
        error("inq_format: %s",  nc_strerror(err));

    def_dims(ncid);
    def_vars(ncid);

    err =  nc_enddef(ncid);
    IF (err != NC_NOERR)
        error("enddef: %s",  nc_strerror(err));

    /* check if can detect a bad file ID */
    err = nc_put_varm_longlong(BAD_ID, 0, NULL, NULL, NULL, NULL, NULL);
    IF (err != NC_EBADID)
        error("expecting NC_EBADID but got %s",nc_err_code_name(err));
    ELSE_NOK

    /* check if can detect a bad variable ID */
    err = nc_put_varm_longlong(ncid, BAD_VARID, NULL, NULL, NULL, NULL, NULL);
    IF (err != NC_ENOTVAR)
        error("expecting NC_ENOTVAR but got %s",nc_err_code_name(err));
    ELSE_NOK

    for (i = 0; i < numVars; i++) {
        assert(var_rank[i] <= MAX_RANK);
        assert(var_nels[i] <= MAX_NELS);

        value[0] = 5; /* reset to a value within bounds */

        /* check if can detect a bad file ID */
        err = nc_put_varm_longlong(BAD_ID, i, NULL, NULL, NULL, NULL, value);
        IF (err != NC_EBADID)
            error("expecting NC_EBADID but got %s",nc_err_code_name(err));
        ELSE_NOK

        canConvert = (var_type[i] == NC_CHAR) == (NCT_LONGLONG == NCT_TEXT);

        for (j = 0; j < var_rank[i]; j++) {
            start[j] = 0;
            edge[j] = 1;
            stride[j] = 1;
            imap[j] = 1;
        }


        /* first test when edge[*] > 0 */
        for (j = 0; j < var_rank[i]; j++) {
            if (var_dimid[i][j] == RECDIM) continue; /* skip record dim */
            start[j] = var_shape[i][j];   /* out of boundary check */
            err = nc_put_varm_longlong(ncid, i, start, edge, stride, imap, value);
            if (!canConvert) {
                IF (err != NC_ECHAR)
                    error("expecting NC_ECHAR but got %s",nc_err_code_name(err));
                ELSE_NOK
                start[j] = 0;
                continue;
            }
            IF (err != NC_EINVALCOORDS)
                error("expecting NC_EINVALCOORDS but got %s",nc_err_code_name(err));
            ELSE_NOK
            start[j] = 0;
            edge[j] = var_shape[i][j] + 1;
            err = nc_put_varm_longlong(ncid, i, start, edge, stride, imap, value);
            IF (err != NC_EEDGE)
                error("expecting NC_EEDGE but got %s",nc_err_code_name(err));
            ELSE_NOK
            edge[j] = 1;
            stride[j] = 0;
            err = nc_put_varm_longlong(ncid, i, start, edge, stride, imap, value);
            IF (err != NC_ESTRIDE)
                error("expecting NC_ESTRIDE but got %s",nc_err_code_name(err));
            ELSE_NOK
            stride[j] = 1;
        }
        /* Check correct error returned when nothing to put, i.e. edge[*]==0 */
        for (j = 0; j < var_rank[i]; j++) edge[j] = 0;

        for (j = 0; j < var_rank[i]; j++) {
            if (var_dimid[i][j] == RECDIM) continue; /* skip record dim */
            start[j] = var_shape[i][j];
            err = nc_put_varm_longlong(ncid, i, start, edge, stride, imap, value);
            if (!canConvert) {
                IF (err != NC_ECHAR)
                    error("expecting NC_ECHAR but got %s",nc_err_code_name(err));
                ELSE_NOK
                start[j] = 0;
                continue;
            }
#ifdef RELAX_COORD_BOUND
            IF (err != NC_NOERR) /* allowed when edge[j]==0 */
                error("expecting NC_NOERR but got %s",nc_err_code_name(err));
#else
            IF (err != NC_EINVALCOORDS) /* not allowed even when edge[j]==0 */
                error("expecting NC_EINVALCOORDS but got %s",nc_err_code_name(err));
#endif
            ELSE_NOK
            start[j] = var_shape[i][j]+1; /* out of boundary check */
            err = nc_put_varm_longlong(ncid, i, start, edge, stride, imap, value);
            IF (err != NC_EINVALCOORDS)
                error("expecting NC_EINVALCOORDS but got %s",nc_err_code_name(err));
            ELSE_NOK
            start[j] = 0;
        }
        for (j = 0; j < var_rank[i]; j++) edge[j] = 1;

        /* Choose a random point dividing each dim into 2 parts */
        /* Put 2^rank (nslabs) slabs so defined */
        nslabs = 1;
        for (j = 0; j < var_rank[i]; j++) {
            mid[j] = roll( var_shape[i][j] );
            nslabs *= 2;
        }
        /* bits of k determine whether to put lower or upper part of dim */
        /* choose random stride from 1 to edge */
        for (k = 0; k < nslabs; k++) {
            nstarts = 1;
            for (j = 0; j < var_rank[i]; j++) {
                if ((k >> j) & 1) {
                    start[j] = 0;
                    edge[j] = mid[j];
                } else {
                    start[j] = mid[j];
                    edge[j] = var_shape[i][j] - mid[j];
                }
                sstride[j] = edge[j] > 0 ? 1+roll(edge[j]) : 1;
                stride[j] = (ptrdiff_t)sstride[j];
                nstarts *= stride[j];
            }
            for (m = 0; m < nstarts; m++) {
                err = toMixedBase(m, var_rank[i], sstride, index);
                IF (err != 0) error("error in toMixedBase");
                nels = 1;
                for (j = 0; j < var_rank[i]; j++) {
                    count[j] = 1 + (edge[j] - index[j] - 1) / (size_t)stride[j];
                    nels *= count[j];
                    index[j] += start[j];
                }
                /* Random choice of forward or backward */
/* TODO
                if ( roll(2) ) {
                    for (j = 0; j < var_rank[i]; j++) {
                        index[j] += (count[j] - 1) * (size_t)stride[j];
                        stride[j] = -stride[j];
                    }
                }
*/
                if (var_rank[i] > 0) {
                    int jj = var_rank[i] - 1;
                    imap[jj] = 1;
                    for (; jj > 0; jj--)
                        imap[jj-1] = imap[jj] * (ptrdiff_t)count[jj];
                }
                for (allInExtRange = 1, j = 0; j < nels; j++) {
                    err = toMixedBase(j, var_rank[i], count, index2);
                    IF (err != 0) error("error in toMixedBase");
                    for (d = 0; d < var_rank[i]; d++)
                        index2[d] = index[d] + index2[d] * (size_t)stride[d];
                    value[j] = hash_longlong(cdf_format,var_type[i], var_rank[i],
                                       index2, NCT_LONGLONG);
                    
                        allInExtRange &= inRange3(cdf_format, (double)value[j],
                                                  var_type[i], NCT_LONGLONG);
                }
                err = nc_put_varm_longlong(ncid,i,index,count,stride,imap,value);
                if (canConvert) {
                    if (allInExtRange) {
                        IF (err != NC_NOERR)
                            error("expecting NC_NOERR but got %s",nc_err_code_name(err));
                        ELSE_NOK
                    }
                    
                    else {

                        IF (err != NC_ERANGE)
                            error("expecting NC_ERANGE but got %s",nc_err_code_name(err));
                        ELSE_NOK
                    }


                } else {
                    IF (err != NC_ECHAR)
                        error("expecting NC_ECHAR but got %s",nc_err_code_name(err));
                    ELSE_NOK
                }
            }
        }
    }

    err =  nc_close(ncid);
    IF (err != NC_NOERR)
        error("close: %s",  nc_strerror(err));

    nok += check_vars_longlong(scratch, numVars);

    err = nc_delete(scratch);
    IF (err != NC_NOERR)
        error("delete file %s failed", scratch);
    return nok;
}

int
test_nc_put_varm_ulonglong(void)
{
    int i, k, d, err, nslabs, ncid, cdf_format, nok=0;
    int canConvert;     /* Both text or both numeric */
    int allInExtRange;  /* all values within external range? */
    size_t j, m, nels;
    size_t start[MAX_RANK], edge[MAX_RANK], index[MAX_RANK];
    size_t index2[MAX_RANK], mid[MAX_RANK], count[MAX_RANK];
    size_t sstride[MAX_RANK];
    ptrdiff_t nstarts;   /* number of different starts */
    ptrdiff_t stride[MAX_RANK], imap[MAX_RANK];
    ulonglong value[MAX_NELS];

    err = file_create(scratch, NC_CLOBBER, &ncid);
    IF (err != NC_NOERR) {
        error("create: %s",  nc_strerror(err));
        return nok;
    }

    err =  nc_inq_format(ncid, &cdf_format);
    IF (err != NC_NOERR)
        error("inq_format: %s",  nc_strerror(err));

    def_dims(ncid);
    def_vars(ncid);

    err =  nc_enddef(ncid);
    IF (err != NC_NOERR)
        error("enddef: %s",  nc_strerror(err));

    /* check if can detect a bad file ID */
    err = nc_put_varm_ulonglong(BAD_ID, 0, NULL, NULL, NULL, NULL, NULL);
    IF (err != NC_EBADID)
        error("expecting NC_EBADID but got %s",nc_err_code_name(err));
    ELSE_NOK

    /* check if can detect a bad variable ID */
    err = nc_put_varm_ulonglong(ncid, BAD_VARID, NULL, NULL, NULL, NULL, NULL);
    IF (err != NC_ENOTVAR)
        error("expecting NC_ENOTVAR but got %s",nc_err_code_name(err));
    ELSE_NOK

    for (i = 0; i < numVars; i++) {
        assert(var_rank[i] <= MAX_RANK);
        assert(var_nels[i] <= MAX_NELS);

        value[0] = 5; /* reset to a value within bounds */

        /* check if can detect a bad file ID */
        err = nc_put_varm_ulonglong(BAD_ID, i, NULL, NULL, NULL, NULL, value);
        IF (err != NC_EBADID)
            error("expecting NC_EBADID but got %s",nc_err_code_name(err));
        ELSE_NOK

        canConvert = (var_type[i] == NC_CHAR) == (NCT_ULONGLONG == NCT_TEXT);

        for (j = 0; j < var_rank[i]; j++) {
            start[j] = 0;
            edge[j] = 1;
            stride[j] = 1;
            imap[j] = 1;
        }


        /* first test when edge[*] > 0 */
        for (j = 0; j < var_rank[i]; j++) {
            if (var_dimid[i][j] == RECDIM) continue; /* skip record dim */
            start[j] = var_shape[i][j];   /* out of boundary check */
            err = nc_put_varm_ulonglong(ncid, i, start, edge, stride, imap, value);
            if (!canConvert) {
                IF (err != NC_ECHAR)
                    error("expecting NC_ECHAR but got %s",nc_err_code_name(err));
                ELSE_NOK
                start[j] = 0;
                continue;
            }
            IF (err != NC_EINVALCOORDS)
                error("expecting NC_EINVALCOORDS but got %s",nc_err_code_name(err));
            ELSE_NOK
            start[j] = 0;
            edge[j] = var_shape[i][j] + 1;
            err = nc_put_varm_ulonglong(ncid, i, start, edge, stride, imap, value);
            IF (err != NC_EEDGE)
                error("expecting NC_EEDGE but got %s",nc_err_code_name(err));
            ELSE_NOK
            edge[j] = 1;
            stride[j] = 0;
            err = nc_put_varm_ulonglong(ncid, i, start, edge, stride, imap, value);
            IF (err != NC_ESTRIDE)
                error("expecting NC_ESTRIDE but got %s",nc_err_code_name(err));
            ELSE_NOK
            stride[j] = 1;
        }
        /* Check correct error returned when nothing to put, i.e. edge[*]==0 */
        for (j = 0; j < var_rank[i]; j++) edge[j] = 0;

        for (j = 0; j < var_rank[i]; j++) {
            if (var_dimid[i][j] == RECDIM) continue; /* skip record dim */
            start[j] = var_shape[i][j];
            err = nc_put_varm_ulonglong(ncid, i, start, edge, stride, imap, value);
            if (!canConvert) {
                IF (err != NC_ECHAR)
                    error("expecting NC_ECHAR but got %s",nc_err_code_name(err));
                ELSE_NOK
                start[j] = 0;
                continue;
            }
#ifdef RELAX_COORD_BOUND
            IF (err != NC_NOERR) /* allowed when edge[j]==0 */
                error("expecting NC_NOERR but got %s",nc_err_code_name(err));
#else
            IF (err != NC_EINVALCOORDS) /* not allowed even when edge[j]==0 */
                error("expecting NC_EINVALCOORDS but got %s",nc_err_code_name(err));
#endif
            ELSE_NOK
            start[j] = var_shape[i][j]+1; /* out of boundary check */
            err = nc_put_varm_ulonglong(ncid, i, start, edge, stride, imap, value);
            IF (err != NC_EINVALCOORDS)
                error("expecting NC_EINVALCOORDS but got %s",nc_err_code_name(err));
            ELSE_NOK
            start[j] = 0;
        }
        for (j = 0; j < var_rank[i]; j++) edge[j] = 1;

        /* Choose a random point dividing each dim into 2 parts */
        /* Put 2^rank (nslabs) slabs so defined */
        nslabs = 1;
        for (j = 0; j < var_rank[i]; j++) {
            mid[j] = roll( var_shape[i][j] );
            nslabs *= 2;
        }
        /* bits of k determine whether to put lower or upper part of dim */
        /* choose random stride from 1 to edge */
        for (k = 0; k < nslabs; k++) {
            nstarts = 1;
            for (j = 0; j < var_rank[i]; j++) {
                if ((k >> j) & 1) {
                    start[j] = 0;
                    edge[j] = mid[j];
                } else {
                    start[j] = mid[j];
                    edge[j] = var_shape[i][j] - mid[j];
                }
                sstride[j] = edge[j] > 0 ? 1+roll(edge[j]) : 1;
                stride[j] = (ptrdiff_t)sstride[j];
                nstarts *= stride[j];
            }
            for (m = 0; m < nstarts; m++) {
                err = toMixedBase(m, var_rank[i], sstride, index);
                IF (err != 0) error("error in toMixedBase");
                nels = 1;
                for (j = 0; j < var_rank[i]; j++) {
                    count[j] = 1 + (edge[j] - index[j] - 1) / (size_t)stride[j];
                    nels *= count[j];
                    index[j] += start[j];
                }
                /* Random choice of forward or backward */
/* TODO
                if ( roll(2) ) {
                    for (j = 0; j < var_rank[i]; j++) {
                        index[j] += (count[j] - 1) * (size_t)stride[j];
                        stride[j] = -stride[j];
                    }
                }
*/
                if (var_rank[i] > 0) {
                    int jj = var_rank[i] - 1;
                    imap[jj] = 1;
                    for (; jj > 0; jj--)
                        imap[jj-1] = imap[jj] * (ptrdiff_t)count[jj];
                }
                for (allInExtRange = 1, j = 0; j < nels; j++) {
                    err = toMixedBase(j, var_rank[i], count, index2);
                    IF (err != 0) error("error in toMixedBase");
                    for (d = 0; d < var_rank[i]; d++)
                        index2[d] = index[d] + index2[d] * (size_t)stride[d];
                    value[j] = hash_ulonglong(cdf_format,var_type[i], var_rank[i],
                                       index2, NCT_ULONGLONG);
                    
                        allInExtRange &= inRange3(cdf_format, (double)value[j],
                                                  var_type[i], NCT_ULONGLONG);
                }
                err = nc_put_varm_ulonglong(ncid,i,index,count,stride,imap,value);
                if (canConvert) {
                    if (allInExtRange) {
                        IF (err != NC_NOERR)
                            error("expecting NC_NOERR but got %s",nc_err_code_name(err));
                        ELSE_NOK
                    }
                    
                    else {

                        IF (err != NC_ERANGE)
                            error("expecting NC_ERANGE but got %s",nc_err_code_name(err));
                        ELSE_NOK
                    }


                } else {
                    IF (err != NC_ECHAR)
                        error("expecting NC_ECHAR but got %s",nc_err_code_name(err));
                    ELSE_NOK
                }
            }
        }
    }

    err =  nc_close(ncid);
    IF (err != NC_NOERR)
        error("close: %s",  nc_strerror(err));

    nok += check_vars_ulonglong(scratch, numVars);

    err = nc_delete(scratch);
    IF (err != NC_NOERR)
        error("delete file %s failed", scratch);
    return nok;
}



int
test_nc_put_att_text(void)
{
    int i, j, err, ncid, nok=0;
    double dtmp;
    size_t k, ndx[1];
    text value[MAX_NELS];

    err = file_create(scratch, NC_NOCLOBBER, &ncid);
    IF (err != NC_NOERR) {
        error("create: %s",  nc_strerror(err));
        return nok;
    }
    def_dims(ncid);
    def_vars(ncid);

    /* check if can detect a bad file ID */
    err = nc_put_att_text(BAD_ID, 0, NULL, 0, NULL);
    IF (err != NC_EBADID)
        error("expecting NC_EBADID but got %s",nc_err_code_name(err));
    ELSE_NOK

    /* check if can detect a bad variable ID */
    err = nc_put_att_text(ncid, BAD_VARID, NULL, 0, NULL);
    IF (err != NC_ENOTVAR)
        error("expecting NC_ENOTVAR but got %s",nc_err_code_name(err));
    ELSE_NOK

    {
        const char *const tval = "value for bad name";
        const size_t tval_len = (size_t)strlen(tval);

        err = nc_put_att_text(ncid, 0, "", tval_len, tval);
        IF (err != NC_EBADNAME)
           error("expecting NC_EBADNAME but got %s",nc_err_code_name(err));
        ELSE_NOK
    }
    for (i = -1; i < numVars; i++) {
        for (j = 0; j < NATTS(i); j++) {
            if (ATT_TYPE(i,j) == NC_CHAR) {
                assert(ATT_LEN(i,j) <= MAX_NELS);

                err = nc_put_att_text(ncid, BAD_VARID, ATT_NAME(i,j), ATT_LEN(i,j), value);
                IF (err != NC_ENOTVAR)
                    error("expecting NC_ENOTVAR but got %s",nc_err_code_name(err));
                ELSE_NOK

                for (k = 0; k < ATT_LEN(i,j); k++) {
                    ndx[0] = k;
                    dtmp = hash(ATT_TYPE(i,j), -1, ndx);
                    value[k] = (text)dtmp;
                }
                err = nc_put_att_text(ncid, i, ATT_NAME(i,j), ATT_LEN(i,j), value);
                IF (err != NC_NOERR)
                    error("expecting NC_NOERR but got %s",nc_err_code_name(err));
                ELSE_NOK
            }
        }
    }

    nok += check_atts_text(ncid, numGatts, numVars);
    err =  nc_close(ncid);
    IF (err != NC_NOERR)
        error("close: %s",  nc_strerror(err));

    err = nc_delete(scratch);
    IF (err != NC_NOERR)
        error("delete file %s failed", scratch);
    return nok;
}



int
test_nc_put_att_uchar(void)
{
    int i, j, err, ncid, cdf_format, nok=0;
    int allInExtRange;  /* all values within external range? */
    size_t k, ndx[1];
    uchar value[MAX_NELS];

    err = file_create(scratch, NC_NOCLOBBER, &ncid);
    IF (err != NC_NOERR) {
        error("create: %s",  nc_strerror(err));
        return nok;
    }

    err =  nc_inq_format(ncid, &cdf_format);
    IF (err != NC_NOERR)
        error("inq_format: %s",  nc_strerror(err));

    def_dims(ncid);
    def_vars(ncid);

    /* check if can detect a bad file ID */
    err = nc_put_att_uchar(BAD_ID, 0, NULL, 0, 0, NULL);
    IF (err != NC_EBADID)
        error("expecting NC_EBADID but got %s",nc_err_code_name(err));
    ELSE_NOK

    /* check if can detect a bad variable ID */
    err = nc_put_att_uchar(ncid, BAD_VARID, NULL, 0, 0, NULL);
    IF (err != NC_ENOTVAR)
        error("expecting NC_ENOTVAR but got %s",nc_err_code_name(err));
    ELSE_NOK

    for (i = -1; i < numVars; i++) {
        for (j = 0; j < NATTS(i); j++) {
            if (!(ATT_TYPE(i,j) == NC_CHAR)) {
                assert(ATT_LEN(i,j) <= MAX_NELS);

                err = nc_put_att_uchar(ncid, BAD_VARID, ATT_NAME(i,j), ATT_TYPE(i,j), ATT_LEN(i,j), value);
                IF (err != NC_ENOTVAR)
                    error("expecting NC_ENOTVAR but got %s",nc_err_code_name(err));
                ELSE_NOK

                /* check if can detect a bad name */
                err = nc_put_att_uchar(ncid, i, NULL, 0, 0, NULL);
                IF (err != NC_EBADNAME)
                    error("expecting NC_EBADNAME but got %s",nc_err_code_name(err));
                ELSE_NOK

                err = nc_put_att_uchar(ncid, i, ATT_NAME(i,j), BAD_TYPE, ATT_LEN(i,j), value);
                IF (err != NC_EBADTYPE)
                    error("expecting NC_EBADTYPE but got %s",nc_err_code_name(err));
                ELSE_NOK

                for (allInExtRange = 1, k = 0; k < ATT_LEN(i,j); k++) {
                    ndx[0] = k;
                    value[k] = hash_uchar(cdf_format,ATT_TYPE(i,j), -1, ndx, NCT_UCHAR);
                    
                        allInExtRange &= inRange3(cdf_format, (double)value[k], ATT_TYPE(i,j), NCT_UCHAR);
                }
                err = nc_put_att_uchar(ncid, i, ATT_NAME(i,j), ATT_TYPE(i,j), ATT_LEN(i,j), value);
                if (allInExtRange) {
                    IF (err != NC_NOERR)
                        error("expecting NC_NOERR but got %s",nc_err_code_name(err));
                    ELSE_NOK
                }
                
#if !defined(USE_PNETCDF) || (PNETCDF_VERSION_MAJOR==1 && PNETCDF_VERSION_MINOR>=8)
                    else {

                        IF (err != NC_ERANGE)
                            error("expecting NC_ERANGE but got %s",nc_err_code_name(err));
                        ELSE_NOK
                    }
#endif

            }
        }
    }

    nok += check_atts_uchar(ncid, numGatts, numVars);
    err =  nc_close(ncid);
    IF (err != NC_NOERR)
        error("close: %s",  nc_strerror(err));

    err = nc_delete(scratch);
    IF (err != NC_NOERR)
        error("delete file %s failed", scratch);
    return nok;
}

int
test_nc_put_att_schar(void)
{
    int i, j, err, ncid, cdf_format, nok=0;
    int allInExtRange;  /* all values within external range? */
    size_t k, ndx[1];
    schar value[MAX_NELS];

    err = file_create(scratch, NC_NOCLOBBER, &ncid);
    IF (err != NC_NOERR) {
        error("create: %s",  nc_strerror(err));
        return nok;
    }

    err =  nc_inq_format(ncid, &cdf_format);
    IF (err != NC_NOERR)
        error("inq_format: %s",  nc_strerror(err));

    def_dims(ncid);
    def_vars(ncid);

    /* check if can detect a bad file ID */
    err = nc_put_att_schar(BAD_ID, 0, NULL, 0, 0, NULL);
    IF (err != NC_EBADID)
        error("expecting NC_EBADID but got %s",nc_err_code_name(err));
    ELSE_NOK

    /* check if can detect a bad variable ID */
    err = nc_put_att_schar(ncid, BAD_VARID, NULL, 0, 0, NULL);
    IF (err != NC_ENOTVAR)
        error("expecting NC_ENOTVAR but got %s",nc_err_code_name(err));
    ELSE_NOK

    for (i = -1; i < numVars; i++) {
        for (j = 0; j < NATTS(i); j++) {
            if (!(ATT_TYPE(i,j) == NC_CHAR)) {
                assert(ATT_LEN(i,j) <= MAX_NELS);

                err = nc_put_att_schar(ncid, BAD_VARID, ATT_NAME(i,j), ATT_TYPE(i,j), ATT_LEN(i,j), value);
                IF (err != NC_ENOTVAR)
                    error("expecting NC_ENOTVAR but got %s",nc_err_code_name(err));
                ELSE_NOK

                /* check if can detect a bad name */
                err = nc_put_att_schar(ncid, i, NULL, 0, 0, NULL);
                IF (err != NC_EBADNAME)
                    error("expecting NC_EBADNAME but got %s",nc_err_code_name(err));
                ELSE_NOK

                err = nc_put_att_schar(ncid, i, ATT_NAME(i,j), BAD_TYPE, ATT_LEN(i,j), value);
                IF (err != NC_EBADTYPE)
                    error("expecting NC_EBADTYPE but got %s",nc_err_code_name(err));
                ELSE_NOK

                for (allInExtRange = 1, k = 0; k < ATT_LEN(i,j); k++) {
                    ndx[0] = k;
                    value[k] = hash_schar(cdf_format,ATT_TYPE(i,j), -1, ndx, NCT_SCHAR);
                    
                        allInExtRange &= inRange3(cdf_format, (double)value[k], ATT_TYPE(i,j), NCT_SCHAR);
                }
                err = nc_put_att_schar(ncid, i, ATT_NAME(i,j), ATT_TYPE(i,j), ATT_LEN(i,j), value);
                if (allInExtRange) {
                    IF (err != NC_NOERR)
                        error("expecting NC_NOERR but got %s",nc_err_code_name(err));
                    ELSE_NOK
                }
                
#if defined(USE_PNETCDF) && PNETCDF_VERSION_MAJOR==1 && PNETCDF_VERSION_MINOR<7
                    else if (cdf_format < NC_FORMAT_CDF5) {
#else
                    else {
#endif
                        IF (err != NC_ERANGE)
                            error("expecting NC_ERANGE but got %s",nc_err_code_name(err));
                        ELSE_NOK
                    }


            }
        }
    }

    nok += check_atts_schar(ncid, numGatts, numVars);
    err =  nc_close(ncid);
    IF (err != NC_NOERR)
        error("close: %s",  nc_strerror(err));

    err = nc_delete(scratch);
    IF (err != NC_NOERR)
        error("delete file %s failed", scratch);
    return nok;
}

int
test_nc_put_att_short(void)
{
    int i, j, err, ncid, cdf_format, nok=0;
    int allInExtRange;  /* all values within external range? */
    size_t k, ndx[1];
    short value[MAX_NELS];

    err = file_create(scratch, NC_NOCLOBBER, &ncid);
    IF (err != NC_NOERR) {
        error("create: %s",  nc_strerror(err));
        return nok;
    }

    err =  nc_inq_format(ncid, &cdf_format);
    IF (err != NC_NOERR)
        error("inq_format: %s",  nc_strerror(err));

    def_dims(ncid);
    def_vars(ncid);

    /* check if can detect a bad file ID */
    err = nc_put_att_short(BAD_ID, 0, NULL, 0, 0, NULL);
    IF (err != NC_EBADID)
        error("expecting NC_EBADID but got %s",nc_err_code_name(err));
    ELSE_NOK

    /* check if can detect a bad variable ID */
    err = nc_put_att_short(ncid, BAD_VARID, NULL, 0, 0, NULL);
    IF (err != NC_ENOTVAR)
        error("expecting NC_ENOTVAR but got %s",nc_err_code_name(err));
    ELSE_NOK

    for (i = -1; i < numVars; i++) {
        for (j = 0; j < NATTS(i); j++) {
            if (!(ATT_TYPE(i,j) == NC_CHAR)) {
                assert(ATT_LEN(i,j) <= MAX_NELS);

                err = nc_put_att_short(ncid, BAD_VARID, ATT_NAME(i,j), ATT_TYPE(i,j), ATT_LEN(i,j), value);
                IF (err != NC_ENOTVAR)
                    error("expecting NC_ENOTVAR but got %s",nc_err_code_name(err));
                ELSE_NOK

                /* check if can detect a bad name */
                err = nc_put_att_short(ncid, i, NULL, 0, 0, NULL);
                IF (err != NC_EBADNAME)
                    error("expecting NC_EBADNAME but got %s",nc_err_code_name(err));
                ELSE_NOK

                err = nc_put_att_short(ncid, i, ATT_NAME(i,j), BAD_TYPE, ATT_LEN(i,j), value);
                IF (err != NC_EBADTYPE)
                    error("expecting NC_EBADTYPE but got %s",nc_err_code_name(err));
                ELSE_NOK

                for (allInExtRange = 1, k = 0; k < ATT_LEN(i,j); k++) {
                    ndx[0] = k;
                    value[k] = hash_short(cdf_format,ATT_TYPE(i,j), -1, ndx, NCT_SHORT);
                    
                        allInExtRange &= inRange3(cdf_format, (double)value[k], ATT_TYPE(i,j), NCT_SHORT);
                }
                err = nc_put_att_short(ncid, i, ATT_NAME(i,j), ATT_TYPE(i,j), ATT_LEN(i,j), value);
                if (allInExtRange) {
                    IF (err != NC_NOERR)
                        error("expecting NC_NOERR but got %s",nc_err_code_name(err));
                    ELSE_NOK
                }
                
                    else {

                        IF (err != NC_ERANGE)
                            error("expecting NC_ERANGE but got %s",nc_err_code_name(err));
                        ELSE_NOK
                    }


            }
        }
    }

    nok += check_atts_short(ncid, numGatts, numVars);
    err =  nc_close(ncid);
    IF (err != NC_NOERR)
        error("close: %s",  nc_strerror(err));

    err = nc_delete(scratch);
    IF (err != NC_NOERR)
        error("delete file %s failed", scratch);
    return nok;
}

int
test_nc_put_att_int(void)
{
    int i, j, err, ncid, cdf_format, nok=0;
    int allInExtRange;  /* all values within external range? */
    size_t k, ndx[1];
    int value[MAX_NELS];

    err = file_create(scratch, NC_NOCLOBBER, &ncid);
    IF (err != NC_NOERR) {
        error("create: %s",  nc_strerror(err));
        return nok;
    }

    err =  nc_inq_format(ncid, &cdf_format);
    IF (err != NC_NOERR)
        error("inq_format: %s",  nc_strerror(err));

    def_dims(ncid);
    def_vars(ncid);

    /* check if can detect a bad file ID */
    err = nc_put_att_int(BAD_ID, 0, NULL, 0, 0, NULL);
    IF (err != NC_EBADID)
        error("expecting NC_EBADID but got %s",nc_err_code_name(err));
    ELSE_NOK

    /* check if can detect a bad variable ID */
    err = nc_put_att_int(ncid, BAD_VARID, NULL, 0, 0, NULL);
    IF (err != NC_ENOTVAR)
        error("expecting NC_ENOTVAR but got %s",nc_err_code_name(err));
    ELSE_NOK

    for (i = -1; i < numVars; i++) {
        for (j = 0; j < NATTS(i); j++) {
            if (!(ATT_TYPE(i,j) == NC_CHAR)) {
                assert(ATT_LEN(i,j) <= MAX_NELS);

                err = nc_put_att_int(ncid, BAD_VARID, ATT_NAME(i,j), ATT_TYPE(i,j), ATT_LEN(i,j), value);
                IF (err != NC_ENOTVAR)
                    error("expecting NC_ENOTVAR but got %s",nc_err_code_name(err));
                ELSE_NOK

                /* check if can detect a bad name */
                err = nc_put_att_int(ncid, i, NULL, 0, 0, NULL);
                IF (err != NC_EBADNAME)
                    error("expecting NC_EBADNAME but got %s",nc_err_code_name(err));
                ELSE_NOK

                err = nc_put_att_int(ncid, i, ATT_NAME(i,j), BAD_TYPE, ATT_LEN(i,j), value);
                IF (err != NC_EBADTYPE)
                    error("expecting NC_EBADTYPE but got %s",nc_err_code_name(err));
                ELSE_NOK

                for (allInExtRange = 1, k = 0; k < ATT_LEN(i,j); k++) {
                    ndx[0] = k;
                    value[k] = hash_int(cdf_format,ATT_TYPE(i,j), -1, ndx, NCT_INT);
                    
                        allInExtRange &= inRange3(cdf_format, (double)value[k], ATT_TYPE(i,j), NCT_INT);
                }
                err = nc_put_att_int(ncid, i, ATT_NAME(i,j), ATT_TYPE(i,j), ATT_LEN(i,j), value);
                if (allInExtRange) {
                    IF (err != NC_NOERR)
                        error("expecting NC_NOERR but got %s",nc_err_code_name(err));
                    ELSE_NOK
                }
                
                    else {

                        IF (err != NC_ERANGE)
                            error("expecting NC_ERANGE but got %s",nc_err_code_name(err));
                        ELSE_NOK
                    }


            }
        }
    }

    nok += check_atts_int(ncid, numGatts, numVars);
    err =  nc_close(ncid);
    IF (err != NC_NOERR)
        error("close: %s",  nc_strerror(err));

    err = nc_delete(scratch);
    IF (err != NC_NOERR)
        error("delete file %s failed", scratch);
    return nok;
}

int
test_nc_put_att_long(void)
{
    int i, j, err, ncid, cdf_format, nok=0;
    int allInExtRange;  /* all values within external range? */
    size_t k, ndx[1];
    long value[MAX_NELS];

    err = file_create(scratch, NC_NOCLOBBER, &ncid);
    IF (err != NC_NOERR) {
        error("create: %s",  nc_strerror(err));
        return nok;
    }

    err =  nc_inq_format(ncid, &cdf_format);
    IF (err != NC_NOERR)
        error("inq_format: %s",  nc_strerror(err));

    def_dims(ncid);
    def_vars(ncid);

    /* check if can detect a bad file ID */
    err = nc_put_att_long(BAD_ID, 0, NULL, 0, 0, NULL);
    IF (err != NC_EBADID)
        error("expecting NC_EBADID but got %s",nc_err_code_name(err));
    ELSE_NOK

    /* check if can detect a bad variable ID */
    err = nc_put_att_long(ncid, BAD_VARID, NULL, 0, 0, NULL);
    IF (err != NC_ENOTVAR)
        error("expecting NC_ENOTVAR but got %s",nc_err_code_name(err));
    ELSE_NOK

    for (i = -1; i < numVars; i++) {
        for (j = 0; j < NATTS(i); j++) {
            if (!(ATT_TYPE(i,j) == NC_CHAR)) {
                assert(ATT_LEN(i,j) <= MAX_NELS);

                err = nc_put_att_long(ncid, BAD_VARID, ATT_NAME(i,j), ATT_TYPE(i,j), ATT_LEN(i,j), value);
                IF (err != NC_ENOTVAR)
                    error("expecting NC_ENOTVAR but got %s",nc_err_code_name(err));
                ELSE_NOK

                /* check if can detect a bad name */
                err = nc_put_att_long(ncid, i, NULL, 0, 0, NULL);
                IF (err != NC_EBADNAME)
                    error("expecting NC_EBADNAME but got %s",nc_err_code_name(err));
                ELSE_NOK

                err = nc_put_att_long(ncid, i, ATT_NAME(i,j), BAD_TYPE, ATT_LEN(i,j), value);
                IF (err != NC_EBADTYPE)
                    error("expecting NC_EBADTYPE but got %s",nc_err_code_name(err));
                ELSE_NOK

                for (allInExtRange = 1, k = 0; k < ATT_LEN(i,j); k++) {
                    ndx[0] = k;
                    value[k] = hash_long(cdf_format,ATT_TYPE(i,j), -1, ndx, NCT_LONG);
                    
                        allInExtRange &= inRange3(cdf_format, (double)value[k], ATT_TYPE(i,j), NCT_LONG);
                }
                err = nc_put_att_long(ncid, i, ATT_NAME(i,j), ATT_TYPE(i,j), ATT_LEN(i,j), value);
                if (allInExtRange) {
                    IF (err != NC_NOERR)
                        error("expecting NC_NOERR but got %s",nc_err_code_name(err));
                    ELSE_NOK
                }
                
                    else {

                        IF (err != NC_ERANGE)
                            error("expecting NC_ERANGE but got %s",nc_err_code_name(err));
                        ELSE_NOK
                    }


            }
        }
    }

    nok += check_atts_long(ncid, numGatts, numVars);
    err =  nc_close(ncid);
    IF (err != NC_NOERR)
        error("close: %s",  nc_strerror(err));

    err = nc_delete(scratch);
    IF (err != NC_NOERR)
        error("delete file %s failed", scratch);
    return nok;
}

int
test_nc_put_att_float(void)
{
    int i, j, err, ncid, cdf_format, nok=0;
    int allInExtRange;  /* all values within external range? */
    size_t k, ndx[1];
    float value[MAX_NELS];

    err = file_create(scratch, NC_NOCLOBBER, &ncid);
    IF (err != NC_NOERR) {
        error("create: %s",  nc_strerror(err));
        return nok;
    }

    err =  nc_inq_format(ncid, &cdf_format);
    IF (err != NC_NOERR)
        error("inq_format: %s",  nc_strerror(err));

    def_dims(ncid);
    def_vars(ncid);

    /* check if can detect a bad file ID */
    err = nc_put_att_float(BAD_ID, 0, NULL, 0, 0, NULL);
    IF (err != NC_EBADID)
        error("expecting NC_EBADID but got %s",nc_err_code_name(err));
    ELSE_NOK

    /* check if can detect a bad variable ID */
    err = nc_put_att_float(ncid, BAD_VARID, NULL, 0, 0, NULL);
    IF (err != NC_ENOTVAR)
        error("expecting NC_ENOTVAR but got %s",nc_err_code_name(err));
    ELSE_NOK

    for (i = -1; i < numVars; i++) {
        for (j = 0; j < NATTS(i); j++) {
            if (!(ATT_TYPE(i,j) == NC_CHAR)) {
                assert(ATT_LEN(i,j) <= MAX_NELS);

                err = nc_put_att_float(ncid, BAD_VARID, ATT_NAME(i,j), ATT_TYPE(i,j), ATT_LEN(i,j), value);
                IF (err != NC_ENOTVAR)
                    error("expecting NC_ENOTVAR but got %s",nc_err_code_name(err));
                ELSE_NOK

                /* check if can detect a bad name */
                err = nc_put_att_float(ncid, i, NULL, 0, 0, NULL);
                IF (err != NC_EBADNAME)
                    error("expecting NC_EBADNAME but got %s",nc_err_code_name(err));
                ELSE_NOK

                err = nc_put_att_float(ncid, i, ATT_NAME(i,j), BAD_TYPE, ATT_LEN(i,j), value);
                IF (err != NC_EBADTYPE)
                    error("expecting NC_EBADTYPE but got %s",nc_err_code_name(err));
                ELSE_NOK

                for (allInExtRange = 1, k = 0; k < ATT_LEN(i,j); k++) {
                    ndx[0] = k;
                    value[k] = hash_float(cdf_format,ATT_TYPE(i,j), -1, ndx, NCT_FLOAT);
                    
                        allInExtRange &= inRange3(cdf_format, (double)value[k], ATT_TYPE(i,j), NCT_FLOAT);
                }
                err = nc_put_att_float(ncid, i, ATT_NAME(i,j), ATT_TYPE(i,j), ATT_LEN(i,j), value);
                if (allInExtRange) {
                    IF (err != NC_NOERR)
                        error("expecting NC_NOERR but got %s",nc_err_code_name(err));
                    ELSE_NOK
                }
                
                    else {

                        IF (err != NC_ERANGE)
                            error("expecting NC_ERANGE but got %s",nc_err_code_name(err));
                        ELSE_NOK
                    }


            }
        }
    }

    nok += check_atts_float(ncid, numGatts, numVars);
    err =  nc_close(ncid);
    IF (err != NC_NOERR)
        error("close: %s",  nc_strerror(err));

    err = nc_delete(scratch);
    IF (err != NC_NOERR)
        error("delete file %s failed", scratch);
    return nok;
}

int
test_nc_put_att_double(void)
{
    int i, j, err, ncid, cdf_format, nok=0;
    int allInExtRange;  /* all values within external range? */
    size_t k, ndx[1];
    double value[MAX_NELS];

    err = file_create(scratch, NC_NOCLOBBER, &ncid);
    IF (err != NC_NOERR) {
        error("create: %s",  nc_strerror(err));
        return nok;
    }

    err =  nc_inq_format(ncid, &cdf_format);
    IF (err != NC_NOERR)
        error("inq_format: %s",  nc_strerror(err));

    def_dims(ncid);
    def_vars(ncid);

    /* check if can detect a bad file ID */
    err = nc_put_att_double(BAD_ID, 0, NULL, 0, 0, NULL);
    IF (err != NC_EBADID)
        error("expecting NC_EBADID but got %s",nc_err_code_name(err));
    ELSE_NOK

    /* check if can detect a bad variable ID */
    err = nc_put_att_double(ncid, BAD_VARID, NULL, 0, 0, NULL);
    IF (err != NC_ENOTVAR)
        error("expecting NC_ENOTVAR but got %s",nc_err_code_name(err));
    ELSE_NOK

    for (i = -1; i < numVars; i++) {
        for (j = 0; j < NATTS(i); j++) {
            if (!(ATT_TYPE(i,j) == NC_CHAR)) {
                assert(ATT_LEN(i,j) <= MAX_NELS);

                err = nc_put_att_double(ncid, BAD_VARID, ATT_NAME(i,j), ATT_TYPE(i,j), ATT_LEN(i,j), value);
                IF (err != NC_ENOTVAR)
                    error("expecting NC_ENOTVAR but got %s",nc_err_code_name(err));
                ELSE_NOK

                /* check if can detect a bad name */
                err = nc_put_att_double(ncid, i, NULL, 0, 0, NULL);
                IF (err != NC_EBADNAME)
                    error("expecting NC_EBADNAME but got %s",nc_err_code_name(err));
                ELSE_NOK

                err = nc_put_att_double(ncid, i, ATT_NAME(i,j), BAD_TYPE, ATT_LEN(i,j), value);
                IF (err != NC_EBADTYPE)
                    error("expecting NC_EBADTYPE but got %s",nc_err_code_name(err));
                ELSE_NOK

                for (allInExtRange = 1, k = 0; k < ATT_LEN(i,j); k++) {
                    ndx[0] = k;
                    value[k] = hash_double(cdf_format,ATT_TYPE(i,j), -1, ndx, NCT_DOUBLE);
                    
                        allInExtRange &= inRange3(cdf_format, (double)value[k], ATT_TYPE(i,j), NCT_DOUBLE);
                }
                err = nc_put_att_double(ncid, i, ATT_NAME(i,j), ATT_TYPE(i,j), ATT_LEN(i,j), value);
                if (allInExtRange) {
                    IF (err != NC_NOERR)
                        error("expecting NC_NOERR but got %s",nc_err_code_name(err));
                    ELSE_NOK
                }
                
                    else {

                        IF (err != NC_ERANGE)
                            error("expecting NC_ERANGE but got %s",nc_err_code_name(err));
                        ELSE_NOK
                    }


            }
        }
    }

    nok += check_atts_double(ncid, numGatts, numVars);
    err =  nc_close(ncid);
    IF (err != NC_NOERR)
        error("close: %s",  nc_strerror(err));

    err = nc_delete(scratch);
    IF (err != NC_NOERR)
        error("delete file %s failed", scratch);
    return nok;
}

int
test_nc_put_att_ushort(void)
{
    int i, j, err, ncid, cdf_format, nok=0;
    int allInExtRange;  /* all values within external range? */
    size_t k, ndx[1];
    ushort value[MAX_NELS];

    err = file_create(scratch, NC_NOCLOBBER, &ncid);
    IF (err != NC_NOERR) {
        error("create: %s",  nc_strerror(err));
        return nok;
    }

    err =  nc_inq_format(ncid, &cdf_format);
    IF (err != NC_NOERR)
        error("inq_format: %s",  nc_strerror(err));

    def_dims(ncid);
    def_vars(ncid);

    /* check if can detect a bad file ID */
    err = nc_put_att_ushort(BAD_ID, 0, NULL, 0, 0, NULL);
    IF (err != NC_EBADID)
        error("expecting NC_EBADID but got %s",nc_err_code_name(err));
    ELSE_NOK

    /* check if can detect a bad variable ID */
    err = nc_put_att_ushort(ncid, BAD_VARID, NULL, 0, 0, NULL);
    IF (err != NC_ENOTVAR)
        error("expecting NC_ENOTVAR but got %s",nc_err_code_name(err));
    ELSE_NOK

    for (i = -1; i < numVars; i++) {
        for (j = 0; j < NATTS(i); j++) {
            if (!(ATT_TYPE(i,j) == NC_CHAR)) {
                assert(ATT_LEN(i,j) <= MAX_NELS);

                err = nc_put_att_ushort(ncid, BAD_VARID, ATT_NAME(i,j), ATT_TYPE(i,j), ATT_LEN(i,j), value);
                IF (err != NC_ENOTVAR)
                    error("expecting NC_ENOTVAR but got %s",nc_err_code_name(err));
                ELSE_NOK

                /* check if can detect a bad name */
                err = nc_put_att_ushort(ncid, i, NULL, 0, 0, NULL);
                IF (err != NC_EBADNAME)
                    error("expecting NC_EBADNAME but got %s",nc_err_code_name(err));
                ELSE_NOK

                err = nc_put_att_ushort(ncid, i, ATT_NAME(i,j), BAD_TYPE, ATT_LEN(i,j), value);
                IF (err != NC_EBADTYPE)
                    error("expecting NC_EBADTYPE but got %s",nc_err_code_name(err));
                ELSE_NOK

                for (allInExtRange = 1, k = 0; k < ATT_LEN(i,j); k++) {
                    ndx[0] = k;
                    value[k] = hash_ushort(cdf_format,ATT_TYPE(i,j), -1, ndx, NCT_USHORT);
                    
                        allInExtRange &= inRange3(cdf_format, (double)value[k], ATT_TYPE(i,j), NCT_USHORT);
                }
                err = nc_put_att_ushort(ncid, i, ATT_NAME(i,j), ATT_TYPE(i,j), ATT_LEN(i,j), value);
                if (allInExtRange) {
                    IF (err != NC_NOERR)
                        error("expecting NC_NOERR but got %s",nc_err_code_name(err));
                    ELSE_NOK
                }
                
                    else {

                        IF (err != NC_ERANGE)
                            error("expecting NC_ERANGE but got %s",nc_err_code_name(err));
                        ELSE_NOK
                    }


            }
        }
    }

    nok += check_atts_ushort(ncid, numGatts, numVars);
    err =  nc_close(ncid);
    IF (err != NC_NOERR)
        error("close: %s",  nc_strerror(err));

    err = nc_delete(scratch);
    IF (err != NC_NOERR)
        error("delete file %s failed", scratch);
    return nok;
}

int
test_nc_put_att_uint(void)
{
    int i, j, err, ncid, cdf_format, nok=0;
    int allInExtRange;  /* all values within external range? */
    size_t k, ndx[1];
    uint value[MAX_NELS];

    err = file_create(scratch, NC_NOCLOBBER, &ncid);
    IF (err != NC_NOERR) {
        error("create: %s",  nc_strerror(err));
        return nok;
    }

    err =  nc_inq_format(ncid, &cdf_format);
    IF (err != NC_NOERR)
        error("inq_format: %s",  nc_strerror(err));

    def_dims(ncid);
    def_vars(ncid);

    /* check if can detect a bad file ID */
    err = nc_put_att_uint(BAD_ID, 0, NULL, 0, 0, NULL);
    IF (err != NC_EBADID)
        error("expecting NC_EBADID but got %s",nc_err_code_name(err));
    ELSE_NOK

    /* check if can detect a bad variable ID */
    err = nc_put_att_uint(ncid, BAD_VARID, NULL, 0, 0, NULL);
    IF (err != NC_ENOTVAR)
        error("expecting NC_ENOTVAR but got %s",nc_err_code_name(err));
    ELSE_NOK

    for (i = -1; i < numVars; i++) {
        for (j = 0; j < NATTS(i); j++) {
            if (!(ATT_TYPE(i,j) == NC_CHAR)) {
                assert(ATT_LEN(i,j) <= MAX_NELS);

                err = nc_put_att_uint(ncid, BAD_VARID, ATT_NAME(i,j), ATT_TYPE(i,j), ATT_LEN(i,j), value);
                IF (err != NC_ENOTVAR)
                    error("expecting NC_ENOTVAR but got %s",nc_err_code_name(err));
                ELSE_NOK

                /* check if can detect a bad name */
                err = nc_put_att_uint(ncid, i, NULL, 0, 0, NULL);
                IF (err != NC_EBADNAME)
                    error("expecting NC_EBADNAME but got %s",nc_err_code_name(err));
                ELSE_NOK

                err = nc_put_att_uint(ncid, i, ATT_NAME(i,j), BAD_TYPE, ATT_LEN(i,j), value);
                IF (err != NC_EBADTYPE)
                    error("expecting NC_EBADTYPE but got %s",nc_err_code_name(err));
                ELSE_NOK

                for (allInExtRange = 1, k = 0; k < ATT_LEN(i,j); k++) {
                    ndx[0] = k;
                    value[k] = hash_uint(cdf_format,ATT_TYPE(i,j), -1, ndx, NCT_UINT);
                    
                        allInExtRange &= inRange3(cdf_format, (double)value[k], ATT_TYPE(i,j), NCT_UINT);
                }
                err = nc_put_att_uint(ncid, i, ATT_NAME(i,j), ATT_TYPE(i,j), ATT_LEN(i,j), value);
                if (allInExtRange) {
                    IF (err != NC_NOERR)
                        error("expecting NC_NOERR but got %s",nc_err_code_name(err));
                    ELSE_NOK
                }
                
                    else {

                        IF (err != NC_ERANGE)
                            error("expecting NC_ERANGE but got %s",nc_err_code_name(err));
                        ELSE_NOK
                    }


            }
        }
    }

    nok += check_atts_uint(ncid, numGatts, numVars);
    err =  nc_close(ncid);
    IF (err != NC_NOERR)
        error("close: %s",  nc_strerror(err));

    err = nc_delete(scratch);
    IF (err != NC_NOERR)
        error("delete file %s failed", scratch);
    return nok;
}

int
test_nc_put_att_longlong(void)
{
    int i, j, err, ncid, cdf_format, nok=0;
    int allInExtRange;  /* all values within external range? */
    size_t k, ndx[1];
    longlong value[MAX_NELS];

    err = file_create(scratch, NC_NOCLOBBER, &ncid);
    IF (err != NC_NOERR) {
        error("create: %s",  nc_strerror(err));
        return nok;
    }

    err =  nc_inq_format(ncid, &cdf_format);
    IF (err != NC_NOERR)
        error("inq_format: %s",  nc_strerror(err));

    def_dims(ncid);
    def_vars(ncid);

    /* check if can detect a bad file ID */
    err = nc_put_att_longlong(BAD_ID, 0, NULL, 0, 0, NULL);
    IF (err != NC_EBADID)
        error("expecting NC_EBADID but got %s",nc_err_code_name(err));
    ELSE_NOK

    /* check if can detect a bad variable ID */
    err = nc_put_att_longlong(ncid, BAD_VARID, NULL, 0, 0, NULL);
    IF (err != NC_ENOTVAR)
        error("expecting NC_ENOTVAR but got %s",nc_err_code_name(err));
    ELSE_NOK

    for (i = -1; i < numVars; i++) {
        for (j = 0; j < NATTS(i); j++) {
            if (!(ATT_TYPE(i,j) == NC_CHAR)) {
                assert(ATT_LEN(i,j) <= MAX_NELS);

                err = nc_put_att_longlong(ncid, BAD_VARID, ATT_NAME(i,j), ATT_TYPE(i,j), ATT_LEN(i,j), value);
                IF (err != NC_ENOTVAR)
                    error("expecting NC_ENOTVAR but got %s",nc_err_code_name(err));
                ELSE_NOK

                /* check if can detect a bad name */
                err = nc_put_att_longlong(ncid, i, NULL, 0, 0, NULL);
                IF (err != NC_EBADNAME)
                    error("expecting NC_EBADNAME but got %s",nc_err_code_name(err));
                ELSE_NOK

                err = nc_put_att_longlong(ncid, i, ATT_NAME(i,j), BAD_TYPE, ATT_LEN(i,j), value);
                IF (err != NC_EBADTYPE)
                    error("expecting NC_EBADTYPE but got %s",nc_err_code_name(err));
                ELSE_NOK

                for (allInExtRange = 1, k = 0; k < ATT_LEN(i,j); k++) {
                    ndx[0] = k;
                    value[k] = hash_longlong(cdf_format,ATT_TYPE(i,j), -1, ndx, NCT_LONGLONG);
                    
                        allInExtRange &= inRange3(cdf_format, (double)value[k], ATT_TYPE(i,j), NCT_LONGLONG);
                }
                err = nc_put_att_longlong(ncid, i, ATT_NAME(i,j), ATT_TYPE(i,j), ATT_LEN(i,j), value);
                if (allInExtRange) {
                    IF (err != NC_NOERR)
                        error("expecting NC_NOERR but got %s",nc_err_code_name(err));
                    ELSE_NOK
                }
                
                    else {

                        IF (err != NC_ERANGE)
                            error("expecting NC_ERANGE but got %s",nc_err_code_name(err));
                        ELSE_NOK
                    }


            }
        }
    }

    nok += check_atts_longlong(ncid, numGatts, numVars);
    err =  nc_close(ncid);
    IF (err != NC_NOERR)
        error("close: %s",  nc_strerror(err));

    err = nc_delete(scratch);
    IF (err != NC_NOERR)
        error("delete file %s failed", scratch);
    return nok;
}

int
test_nc_put_att_ulonglong(void)
{
    int i, j, err, ncid, cdf_format, nok=0;
    int allInExtRange;  /* all values within external range? */
    size_t k, ndx[1];
    ulonglong value[MAX_NELS];

    err = file_create(scratch, NC_NOCLOBBER, &ncid);
    IF (err != NC_NOERR) {
        error("create: %s",  nc_strerror(err));
        return nok;
    }

    err =  nc_inq_format(ncid, &cdf_format);
    IF (err != NC_NOERR)
        error("inq_format: %s",  nc_strerror(err));

    def_dims(ncid);
    def_vars(ncid);

    /* check if can detect a bad file ID */
    err = nc_put_att_ulonglong(BAD_ID, 0, NULL, 0, 0, NULL);
    IF (err != NC_EBADID)
        error("expecting NC_EBADID but got %s",nc_err_code_name(err));
    ELSE_NOK

    /* check if can detect a bad variable ID */
    err = nc_put_att_ulonglong(ncid, BAD_VARID, NULL, 0, 0, NULL);
    IF (err != NC_ENOTVAR)
        error("expecting NC_ENOTVAR but got %s",nc_err_code_name(err));
    ELSE_NOK

    for (i = -1; i < numVars; i++) {
        for (j = 0; j < NATTS(i); j++) {
            if (!(ATT_TYPE(i,j) == NC_CHAR)) {
                assert(ATT_LEN(i,j) <= MAX_NELS);

                err = nc_put_att_ulonglong(ncid, BAD_VARID, ATT_NAME(i,j), ATT_TYPE(i,j), ATT_LEN(i,j), value);
                IF (err != NC_ENOTVAR)
                    error("expecting NC_ENOTVAR but got %s",nc_err_code_name(err));
                ELSE_NOK

                /* check if can detect a bad name */
                err = nc_put_att_ulonglong(ncid, i, NULL, 0, 0, NULL);
                IF (err != NC_EBADNAME)
                    error("expecting NC_EBADNAME but got %s",nc_err_code_name(err));
                ELSE_NOK

                err = nc_put_att_ulonglong(ncid, i, ATT_NAME(i,j), BAD_TYPE, ATT_LEN(i,j), value);
                IF (err != NC_EBADTYPE)
                    error("expecting NC_EBADTYPE but got %s",nc_err_code_name(err));
                ELSE_NOK

                for (allInExtRange = 1, k = 0; k < ATT_LEN(i,j); k++) {
                    ndx[0] = k;
                    value[k] = hash_ulonglong(cdf_format,ATT_TYPE(i,j), -1, ndx, NCT_ULONGLONG);
                    
                        allInExtRange &= inRange3(cdf_format, (double)value[k], ATT_TYPE(i,j), NCT_ULONGLONG);
                }
                err = nc_put_att_ulonglong(ncid, i, ATT_NAME(i,j), ATT_TYPE(i,j), ATT_LEN(i,j), value);
                if (allInExtRange) {
                    IF (err != NC_NOERR)
                        error("expecting NC_NOERR but got %s",nc_err_code_name(err));
                    ELSE_NOK
                }
                
                    else {

                        IF (err != NC_ERANGE)
                            error("expecting NC_ERANGE but got %s",nc_err_code_name(err));
                        ELSE_NOK
                    }


            }
        }
    }

    nok += check_atts_ulonglong(ncid, numGatts, numVars);
    err =  nc_close(ncid);
    IF (err != NC_NOERR)
        error("close: %s",  nc_strerror(err));

    err = nc_delete(scratch);
    IF (err != NC_NOERR)
        error("delete file %s failed", scratch);
    return nok;
}


