1 /*********************************************************************
2  *   Copyright 2018, UCAR/Unidata
3  *   See netcdf/COPYRIGHT file for copying and redistribution conditions.
4  *   $Id: vputgetg.c,v 1.13 2006/10/31 16:19:40 ed Exp $
5  *********************************************************************/
6 
7 #include <config.h>
8 #include <stdio.h>
9 #include <stdlib.h>		/* for free() */
10 #include "netcdf.h"
11 #include "testcdf.h"		/* defines in-memory test cdf structure */
12 #include "add.h"		/* functions to update in-memory netcdf */
13 #include "val.h"
14 #include "error.h"
15 #include "tests.h"
16 #include "emalloc.h"
17 
18 #undef max
19 #define max(A, B)	((A) > (B) ? (A) : (B))
20 
21 /*
22  * For every variable in open netcdf, puts and gets three hypercubes
23  * of data of the appropriate type, comparing values from get to
24  * values put to check that both ncvarputg and ncvargetg worked.  The
25  * three hypercubes are
26  *    - a large hypercube from (0, 0, ...) to the far corner (diagonally
27  *      opposite (0, 0, ...), trivial strides and index mapping vector;
28  *    - a size 1 hypercube from the far corner with edge lengths of 1
29  *      in every direction, trivial strides and index mapping vector; and
30  *    - a hypercube starting about 1/3 of the way along the diagonal
31  *      from (0,0,...) extending 1/3 of the way in every direction
32  *      toward the far corner, dimension-dependent strides and inverted
33  *	index mapping vector rooted at the "upper-left" corned.
34  */
35 
36 int
test_varputgetg(cdfid)37 test_varputgetg(cdfid)
38      int cdfid;			/* handle of netcdf open and in data mode */
39 {
40     int nerrs = 0;
41     static char pname[] = "test_varputgetg";
42     int id = 0, ie = 0, iv = 0;		/* loop indices */
43     int ne = 3;			/* number of test hypercubes for each var */
44     struct cdfhc {		/* a hypercube with generic values */
45 	long cor[MAX_NC_DIMS];	/* netcdf coordinates for lower corner */
46 	long npts[MAX_NC_DIMS];	/* netcdf edge lengths to upper corner */
47 	long strd[MAX_NC_DIMS];	/* external strides */
48 	long imap[MAX_NC_DIMS];	/* internal, index mapping vector */
49 	long offset;		/* offset in bytes to I/O start corner */
50 	void *vals;		/* pointer to block of values */
51     } hc[3], tmp;		/* test hypercubes */
52     long nel[3];		/* number of elements in hypercube */
53 
54     for (iv = 0; iv < test.nvars; iv++)	{ /* for each var in netcdf */
55 
56 		for (ie = 0; ie < ne; ie++)
57 			nel[ie] = 1;		/* to compute space for hypercube values */
58 
59 	/*
60 	 * The following macro returns the size of a dimension for a
61 	 * variable with a maximum  dimension size of 5 for the record
62 	 * dimension.
63 	 */
64 #	define EXTNPTS(varid, idim)	\
65 	    (test.dims[test.vars[varid].dims[id]].size == NC_UNLIMITED \
66 		? 5 \
67 		: test.dims[test.vars[varid].dims[id]].size)
68 #	define STRIDE(idim)		(idim + 2)
69 #	define INTNPTS(extnpts, idim)	(1 + (extnpts - 1) / STRIDE(idim))
70 
71 
72 	for (id = test.vars[iv].ndims-1; id >= 0; --id) { /* set cubes */
73 
74 	    /* start at "lower-left" corner, do whole variable.  unity
75 	     * strides and trivial index mapping */
76 	    hc[0].cor[id]	= 0;
77 	    hc[0].npts[id]	= EXTNPTS(iv, id);
78 	    hc[0].strd[id]	= 1;
79 	    hc[0].imap[id]	= id == test.vars[iv].ndims-1
80 					? nctypelen(test.vars[iv].type)
81 					: hc[0].imap[id+1] * hc[0].npts[id+1];
82 	    nel[0]		*= hc[0].npts[id];
83 	    if (id <= 0)
84 		hc[0].offset	= 0;
85 
86 	    /* start at "upper-right" corner, do one point */
87 	    hc[1].cor[id]	= EXTNPTS(iv, id) - 1;
88 	    hc[1].npts[id]	= 1;
89 	    hc[1].strd[id]	= 1;
90 	    hc[1].imap[id]	= id == test.vars[iv].ndims-1
91 					? nctypelen(test.vars[iv].type)
92 					: hc[1].imap[id+1] * hc[1].npts[id+1];
93 	    nel[1]		*= hc[1].npts[id];
94 	    if (id == 0)
95 		hc[1].offset	= 0;
96 
97 	    /* start about 1/3 way along diagonal, do 1/3 in each direction.
98 	     * dimension-dependent strides; inverted index mapping starting
99 	     * from "upper-right" corner. */
100 	    hc[2].cor[id]	= EXTNPTS(iv, id)/3;
101 	    hc[2].npts[id]	= INTNPTS(max(EXTNPTS(iv, id)/3, 1), id);
102 	    hc[2].strd[id]	= STRIDE(id);
103 	    hc[2].imap[id]	= id == test.vars[iv].ndims-1
104 					? -nctypelen(test.vars[iv].type)
105 					: hc[2].imap[id+1] * hc[2].npts[id+1];
106 	    nel[2]		*= hc[2].npts[id];
107 	    if (id == 0)
108 		hc[2].offset	= (nel[2]-1)*nctypelen(test.vars[iv].type);
109 	}
110 
111 	for (ie = 0; ie < ne; ie++) { /* for each test */
112 	    int nelms = (int)nel[ie]*nctypelen(test.vars[iv].type) + 8;
113 	    /* allocate space for the cube of values */
114 	    hc[ie].vals	= emalloc(nelms);
115 	    tmp.vals = emalloc(nelms);
116 
117 	    /* fill allocated space with different values of right type */
118 	    val_fill(test.vars[iv].type, nel[ie], hc[ie].vals);
119 
120 	    if(ncvarputg (cdfid, iv, hc[ie].cor, hc[ie].npts,
121 			  hc[ie].strd, hc[ie].imap,
122 			  (char*)hc[ie].vals+hc[ie].offset)
123 	       == -1) {
124 		error("%s: ncvarputg failed for point %d, variable %s",
125 		      pname, ie, test.vars[iv].name);
126 		nerrs++;
127 		errvar(&test, &test.vars[iv]);
128 		(void)fprintf(stderr,"  corner = (");
129 		for (id = 0 ; id < test.vars[iv].ndims; id++)
130 		  (void)fprintf(stderr,"%ld%s",(long)hc[ie].cor[id],
131 				(id < test.vars[iv].ndims-1) ? ", " : "");
132 		(void)fprintf(stderr,")\n");
133 		(void)fprintf(stderr,"  npts = (");
134 		for (id = 0 ; id < test.vars[iv].ndims; id++)
135 		  (void)fprintf(stderr,"%ld%s",(long)hc[ie].npts[id],
136 				(id < test.vars[iv].ndims-1) ? ", " : "");
137 		(void)fprintf(stderr,")\n");
138 		(void)fprintf(stderr,"  external strides = (");
139 		for (id = 0 ; id < test.vars[iv].ndims; id++)
140 		  (void)fprintf(stderr,"%ld%s",(long)hc[ie].strd[id],
141 				(id < test.vars[iv].ndims-1) ? ", " : "");
142 		(void)fprintf(stderr,")\n");
143 		(void)fprintf(stderr,"  internal index mapping vector = (");
144 		for (id = 0 ; id < test.vars[iv].ndims; id++)
145 		  (void)fprintf(stderr,"%ld%s",(long)hc[ie].imap[id],
146 				(id < test.vars[iv].ndims-1) ? ", " : "");
147 		(void)fprintf(stderr,")\n");
148 	    } else {
149 		long	dsize[MAX_NC_DIMS];
150 
151 		for (id = 0; id < test.vars[iv].ndims; id++)
152 		    dsize[id]	= EXTNPTS(iv, id);
153 		add_data(&test, iv, hc[ie].cor, dsize);
154 						    /* keep test in sync */
155 		if(ncvargetg (cdfid, iv, hc[ie].cor, hc[ie].npts,
156 			      hc[ie].strd, hc[ie].imap,
157 			      (char*)tmp.vals+hc[ie].offset)
158 		   == -1) {
159 		    error("%s: ncvargetg failed for point %d, variable %s",
160 			  pname, ie, test.vars[iv].name);
161 		    nerrs++;
162 		}
163 		else {
164 		    if (val_cmp(test.vars[iv].type, nel[ie],
165 				hc[ie].vals, tmp.vals) != 0) {
166 			error("%s: bad values returned from ncvargetg",
167 			      pname);
168 			nerrs++;
169 			errvar(&test, &test.vars[iv]); /* describe var */
170 		    }
171 		}
172 	    }
173 
174 	    free (hc[ie].vals);
175 	    free (tmp.vals);
176 	}
177     }
178     return nerrs;
179 }
180