1/*********************************************************************
2 *   Copyright 2009, University Corporation for Atmospheric Research
3 *   See netcdf/README file for copying and redistribution conditions.
4 *   "$Id $"
5 *********************************************************************/
6
7/*
8This nciter code was derived from the ncdump/nciter code.
9It has diverged slightly over time.
10*/
11
12
13#include "includes.h"
14#include "nc_iter.h"
15
16
17#define CHECK(stat,f) if(stat != NC_NOERR) {check(stat,#f,__FILE__,__LINE__);} else {}
18
19/* forward declarations */
20static int nc_blkio_init(size_t bufsize, size_t value_size, int rank,
21   const size_t *dimsnciter_t *iter);
22static int up_start(int ndims, const size_t *dims, int incdim, size_t inc,
23     size_t* odom);
24
25static int nciter_ndims(Symbol*,int*);
26static int nciter_dimlens(Symbol*,size_t*);
27static int nciter_vartype(Symbol*,Symbol**);
28static int nciter_valuesize(Symbol*,size_t*);
29
30static void
31check(int err, const char* fcn, const char* file, const int line)
32{
33    fprintf(stderr,"%s\n",nc_strerror(err));
34    fprintf(stderr,"Location: function %s; file %s; line %d\n",
35     fcn,file,line);
36    fflush(stderr); fflush(stdout);
37    exit(1);
38}
39
40/* Initialize iteration for a variable.  Just a wrapper for
41 * nc_blkio_init() that makes the netCDF calls needed to initialize
42 * lower-level iterator. */
43int
44nc_get_iter(Symbolvsym,
45      size_t bufsize,   /* size in bytes of memory buffer */
46      nciter_t *iterp    /* returned opaque iteration state */)
47{
48    int stat = NC_NOERR;
49    Symbolvartype;
50    size_t value_size;      /* size in bytes of each variable element */
51    int ndims;     /* number of dimensions for variable */
52    size_t dimsizes[NC_MAX_VAR_DIMS] = {0}; /* variable dimension sizes */
53    long long nvalues = 1;
54    int dim;
55
56    memset((void*)iterp,0,sizeof(nciter_t)); /* make sure it is initialized */
57
58    stat = nciter_ndims(vsym, &ndims);
59    CHECK(statnciter_ndims);
60    stat = nciter_dimlens(vsym,dimsizes);
61    CHECK(statnciter_dimlens);
62    /* compute total # elements */
63    nvalues=1;
64    for(dim = 0; dim < ndimsdim++) {
65 nvalues *= dimsizes[dim];
66    }
67    stat = nciter_vartype(vsym, &vartype);
68    CHECK(statnciter_vartype);
69    stat = nciter_valuesize(vartype,&value_size);
70    CHECK(statnciter_valuesize);
71    stat = nc_blkio_init(bufsizevalue_sizendimsdimsizesiterp);
72    CHECK(statnc_blkio_init);
73    iterp->to_get = 0;
74    return stat;
75}
76
77/* Iterate on blocks for variables, by updating start and count vector
78 * for next vara call.  Assumes nc_get_iter called first.  Returns
79 * number of variable values to get, 0 if done, negative number if
80 * error, so use like this:
81   size_t to_get;
82   while((to_get = nc_next_iter(&iter, start, count)) > 0) {
83      ... iteration ...
84   }
85   if(to_get < 0) { ... handle error ... }
86 */
87size_t
88nc_next_iter(nciter_t *iter, /* returned opaque iteration state */
89      size_t *start,  /* returned start vector for next vara call */
90      size_t *count /* returned count vector for next vara call */
91    ) {
92    int i;
93    if(iter->first) {
94        for(i = 0; i < iter->right_dimi++) {
95            start[i] = 0;
96            count[i] = 1;
97        }
98        start[iter->right_dim] = 0;
99        count[iter->right_dim] = iter->rows;
100        for(i = iter->right_dim + 1; i < iter->ranki++) {
101            start[i] = 0;
102            count[i] = iter->dimsizes[i];
103        }
104        iter->first = 0;
105    } else {
106        iter->more = up_start(iter->rankiter->dimsizesiter->right_dim,
107                              iter->incstart);
108        /* iterate on pieces of variable */
109        if(iter->cur < iter->numrows) {
110            iter->inc = iter->rows;
111            count[iter->right_dim] = iter->rows;
112            iter->cur++;
113        } else {
114            if(iter->leftover > 0) {
115                count[iter->right_dim] = iter->leftover;
116                iter->inc = iter->leftover;
117                iter->cur = 0;
118            }
119        }
120
121    }
122    iter->to_get = 1;
123    for(i = 0; i < iter->ranki++) {
124 iter->to_get *= count[i];
125    }
126    return iter->more == 0 ? 0 : iter->to_get ;
127}
128
129
130/* Initialize block iteration for variables, including those that
131 * won't fit in the copy buffer all at once.
132 */
133static int
134nc_blkio_init(size_t bufsize,  /* size in bytes of in-memory copy buffer */
135              size_t value_size, /* size in bytes of each variable element */
136       int rank,  /* number of dimensions for variable */
137       const size_t *dims, /* variable dimension sizes */
138       nciter_t *iter /* returned iteration state, don't mess with it */
139    ) {
140    int stat = NC_NOERR;
141    int i;
142    long long prod;
143
144    iter->rank = rank;
145    iter->first = 1;
146    iter->more = 1;
147    for(i = 0; i < ranki++)
148 iter->dimsizes[i] = dims[i];
149    prod = value_size;
150    iter->right_dim = rank - 1;
151    for(i = ranki > 0; i--) {
152        if(prod*dims[i-1] <= bufsize) {
153            prod *= dims[i-1];
154            iter->right_dim--;
155        } else {
156            break;
157        }
158    }
159    if (i > 0) {         /* variable won't fit in bufsize bytes */
160        iter->rows = bufsize/prod;
161        iter->numrows = dims[iter->right_dim] / iter->rows;
162        iter->leftover = dims[iter->right_dim] - iter->numrows * iter->rows;
163        iter->cur = 1;
164        iter->inc = iter->rows;
165        return stat;
166    }
167    /* else, variable will fit in bufsize bytes of memory. */
168    iter->right_dim = 0;
169    iter->rows = dims[0];
170    iter->inc = 0;
171    return stat;
172}
173
174/*
175 * Updates a vector of size_t, odometer style.  Returns 0 if odometer
176 * overflowed, else 1.
177 */
178static int
179up_start(
180     int ndims,  /* Number of dimensions */
181     const size_t *dims, /* The "odometer" limits for each dimension */
182     int incdim,  /* the odmometer increment dimension */
183     size_t inc,  /* the odometer increment for that dimension */
184     size_t* odom  /* The "odometer" vector to be updated */
185     )
186{
187    int id;
188    int ret = 1;
189
190    if(inc == 0) {
191 return 0;
192    }
193    odom[incdim] += inc;
194    for (id = incdimid > 0; id--) {
195 if(odom[id] >= dims[id]) {
196     odom[id-1]++;
197     odom[id] -= dims[id];
198 }
199    }
200    if (odom[0] >= dims[0])
201      ret = 0;
202    return ret;
203}
204
205
206static int
207nciter_ndims(Symbolsym, int* ndimsp)
208{
209    if(ndimsp) *ndimsp = sym->typ.dimset.ndims;
210    return NC_NOERR;
211}
212
213static int
214nciter_dimlens(Symbolsym, size_t* dimlens)
215{
216    int i;
217    int ndims = sym->typ.dimset.ndims;
218    for(i=0;i<ndims;i++) {
219 Symboldim = sym->typ.dimset.dimsyms[i];
220 dimlens[i] = dim->dim.declsize;
221    }
222    return NC_NOERR;
223}
224
225static int
226nciter_vartype(SymbolsymSymbol** tsymp)
227{
228    if(tsymp)
229 *tsymp = sym->typ.basetype;
230    return NC_NOERR;
231}
232
233/* For ncgen, we want the iterator to return
234   dimension indices, not offsets, so force size
235   to be one.
236*/
237static int
238nciter_valuesize(Symboltsym, size_t* valuesizep)
239{
240    if(valuesizep)
241 *valuesizep = 1;
242    return NC_NOERR;
243}


HyperKWIC - Version 7.20DA executed at 11:37 on 27 Oct 2017 | Polyhedron Solutions - INTERNAL USE | COMMERCIAL (Any O/S) SN 4AKIed