/********************************************************************* * Copyright 2018, UCAR/Unidata * See netcdf/COPYRIGHT file for copying and redistribution conditions. * $Id: vputgetg.c,v 1.13 2006/10/31 16:19:40 ed Exp $ *********************************************************************/ #include #include #include /* for free() */ #include "netcdf.h" #include "testcdf.h" /* defines in-memory test cdf structure */ #include "add.h" /* functions to update in-memory netcdf */ #include "val.h" #include "error.h" #include "tests.h" #include "emalloc.h" #undef max #define max(A, B) ((A) > (B) ? (A) : (B)) /* * For every variable in open netcdf, puts and gets three hypercubes * of data of the appropriate type, comparing values from get to * values put to check that both ncvarputg and ncvargetg worked. The * three hypercubes are * - a large hypercube from (0, 0, ...) to the far corner (diagonally * opposite (0, 0, ...), trivial strides and index mapping vector; * - a size 1 hypercube from the far corner with edge lengths of 1 * in every direction, trivial strides and index mapping vector; and * - a hypercube starting about 1/3 of the way along the diagonal * from (0,0,...) extending 1/3 of the way in every direction * toward the far corner, dimension-dependent strides and inverted * index mapping vector rooted at the "upper-left" corned. */ int test_varputgetg(cdfid) int cdfid; /* handle of netcdf open and in data mode */ { int nerrs = 0; static char pname[] = "test_varputgetg"; int id = 0, ie = 0, iv = 0; /* loop indices */ int ne = 3; /* number of test hypercubes for each var */ struct cdfhc { /* a hypercube with generic values */ long cor[MAX_NC_DIMS]; /* netcdf coordinates for lower corner */ long npts[MAX_NC_DIMS]; /* netcdf edge lengths to upper corner */ long strd[MAX_NC_DIMS]; /* external strides */ long imap[MAX_NC_DIMS]; /* internal, index mapping vector */ long offset; /* offset in bytes to I/O start corner */ void *vals; /* pointer to block of values */ } hc[3], tmp; /* test hypercubes */ long nel[3]; /* number of elements in hypercube */ for (iv = 0; iv < test.nvars; iv++) { /* for each var in netcdf */ for (ie = 0; ie < ne; ie++) nel[ie] = 1; /* to compute space for hypercube values */ /* * The following macro returns the size of a dimension for a * variable with a maximum dimension size of 5 for the record * dimension. */ # define EXTNPTS(varid, idim) \ (test.dims[test.vars[varid].dims[id]].size == NC_UNLIMITED \ ? 5 \ : test.dims[test.vars[varid].dims[id]].size) # define STRIDE(idim) (idim + 2) # define INTNPTS(extnpts, idim) (1 + (extnpts - 1) / STRIDE(idim)) for (id = test.vars[iv].ndims-1; id >= 0; --id) { /* set cubes */ /* start at "lower-left" corner, do whole variable. unity * strides and trivial index mapping */ hc[0].cor[id] = 0; hc[0].npts[id] = EXTNPTS(iv, id); hc[0].strd[id] = 1; hc[0].imap[id] = id == test.vars[iv].ndims-1 ? nctypelen(test.vars[iv].type) : hc[0].imap[id+1] * hc[0].npts[id+1]; nel[0] *= hc[0].npts[id]; if (id <= 0) hc[0].offset = 0; /* start at "upper-right" corner, do one point */ hc[1].cor[id] = EXTNPTS(iv, id) - 1; hc[1].npts[id] = 1; hc[1].strd[id] = 1; hc[1].imap[id] = id == test.vars[iv].ndims-1 ? nctypelen(test.vars[iv].type) : hc[1].imap[id+1] * hc[1].npts[id+1]; nel[1] *= hc[1].npts[id]; if (id == 0) hc[1].offset = 0; /* start about 1/3 way along diagonal, do 1/3 in each direction. * dimension-dependent strides; inverted index mapping starting * from "upper-right" corner. */ hc[2].cor[id] = EXTNPTS(iv, id)/3; hc[2].npts[id] = INTNPTS(max(EXTNPTS(iv, id)/3, 1), id); hc[2].strd[id] = STRIDE(id); hc[2].imap[id] = id == test.vars[iv].ndims-1 ? -nctypelen(test.vars[iv].type) : hc[2].imap[id+1] * hc[2].npts[id+1]; nel[2] *= hc[2].npts[id]; if (id == 0) hc[2].offset = (nel[2]-1)*nctypelen(test.vars[iv].type); } for (ie = 0; ie < ne; ie++) { /* for each test */ int nelms = (int)nel[ie]*nctypelen(test.vars[iv].type) + 8; /* allocate space for the cube of values */ hc[ie].vals = emalloc(nelms); tmp.vals = emalloc(nelms); /* fill allocated space with different values of right type */ val_fill(test.vars[iv].type, nel[ie], hc[ie].vals); if(ncvarputg (cdfid, iv, hc[ie].cor, hc[ie].npts, hc[ie].strd, hc[ie].imap, (char*)hc[ie].vals+hc[ie].offset) == -1) { error("%s: ncvarputg failed for point %d, variable %s", pname, ie, test.vars[iv].name); nerrs++; errvar(&test, &test.vars[iv]); (void)fprintf(stderr," corner = ("); for (id = 0 ; id < test.vars[iv].ndims; id++) (void)fprintf(stderr,"%ld%s",(long)hc[ie].cor[id], (id < test.vars[iv].ndims-1) ? ", " : ""); (void)fprintf(stderr,")\n"); (void)fprintf(stderr," npts = ("); for (id = 0 ; id < test.vars[iv].ndims; id++) (void)fprintf(stderr,"%ld%s",(long)hc[ie].npts[id], (id < test.vars[iv].ndims-1) ? ", " : ""); (void)fprintf(stderr,")\n"); (void)fprintf(stderr," external strides = ("); for (id = 0 ; id < test.vars[iv].ndims; id++) (void)fprintf(stderr,"%ld%s",(long)hc[ie].strd[id], (id < test.vars[iv].ndims-1) ? ", " : ""); (void)fprintf(stderr,")\n"); (void)fprintf(stderr," internal index mapping vector = ("); for (id = 0 ; id < test.vars[iv].ndims; id++) (void)fprintf(stderr,"%ld%s",(long)hc[ie].imap[id], (id < test.vars[iv].ndims-1) ? ", " : ""); (void)fprintf(stderr,")\n"); } else { long dsize[MAX_NC_DIMS]; for (id = 0; id < test.vars[iv].ndims; id++) dsize[id] = EXTNPTS(iv, id); add_data(&test, iv, hc[ie].cor, dsize); /* keep test in sync */ if(ncvargetg (cdfid, iv, hc[ie].cor, hc[ie].npts, hc[ie].strd, hc[ie].imap, (char*)tmp.vals+hc[ie].offset) == -1) { error("%s: ncvargetg failed for point %d, variable %s", pname, ie, test.vars[iv].name); nerrs++; } else { if (val_cmp(test.vars[iv].type, nel[ie], hc[ie].vals, tmp.vals) != 0) { error("%s: bad values returned from ncvargetg", pname); nerrs++; errvar(&test, &test.vars[iv]); /* describe var */ } } } free (hc[ie].vals); free (tmp.vals); } } return nerrs; }