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