1 /*********************************************************************
2 * Copyright 2018, UCAR/Unidata
3 * See netcdf/COPYRIGHT file for copying and redistribution conditions.
4 * $Id: util.c 2792 2014-10-27 06:02:59Z wkliao $
5 *********************************************************************/
6
7 #include <config.h>
8 #include <math.h> /* floor() */
9 #include "tests.h"
10
11 void
print_nok(int nok)12 print_nok(int nok)
13 {
14 if (verbose || nfails > 0)
15 print("\n");
16 print(" %d good comparisons. ", nok);
17 }
18
19
20 /* Is value within external type range? */
21 int
inRange(const double value,const nc_type xtype)22 inRange(const double value, const nc_type xtype)
23 {
24 switch (xtype) {
25 case NC_CHAR: return value >= X_CHAR_MIN && value <= X_CHAR_MAX;
26 case NC_BYTE: return value >= X_BYTE_MIN && value <= X_BYTE_MAX;
27 case NC_SHORT: return value >= X_SHORT_MIN && value <= X_SHORT_MAX;
28 case NC_INT: return value >= X_INT_MIN && value <= X_INT_MAX;
29 case NC_FLOAT: return value >= X_FLOAT_MIN && value <= X_FLOAT_MAX;
30 case NC_DOUBLE: return value >= X_DOUBLE_MIN && value <= X_DOUBLE_MAX;
31 case NC_UBYTE: return value >= 0 && value <= X_UCHAR_MAX;
32 case NC_USHORT: return value >= 0 && value <= X_USHORT_MAX;
33 case NC_UINT: return value >= 0 && value <= X_UINT_MAX;
34 case NC_INT64: return value >= X_INT64_MIN && value <= X_INT64_MAX;
35 case NC_UINT64: return value >= 0 && value <= X_UINT64_MAX;
36 default: assert(0);
37 return(0);
38 }
39 }
40
41 static int
inRange_uchar(const int cdf_format,const double value,const nc_type xtype)42 inRange_uchar(const int cdf_format,
43 const double value,
44 const nc_type xtype)
45 {
46 /* check value of type xtype if within uchar range */
47
48 if (cdf_format < NC_FORMAT_CDF5 && xtype == NC_BYTE) {
49 /* netCDF specification make a special case for type conversion between
50 * uchar and scahr: do not check for range error. See
51 * http://www.unidata.ucar.edu/software/netcdf/docs/data_type.html#type_conversion
52 */
53 return(value >= 0 && value <= 255);
54 /* this is to ensure value is within the range of uchar */
55 }
56 /* else */
57 return inRange(value, xtype);
58 }
59
60 static int
inRange_float(const double value,const nc_type xtype)61 inRange_float(const double value, const nc_type xtype)
62 {
63 double min, max;
64
65 switch (xtype) {
66 case NC_CHAR: min = X_CHAR_MIN; max = X_CHAR_MAX; break;
67 case NC_BYTE: min = X_BYTE_MIN; max = X_BYTE_MAX; break;
68 case NC_SHORT: min = X_SHORT_MIN; max = X_SHORT_MAX; break;
69 case NC_INT: min = X_INT_MIN; max = X_INT_MAX; break;
70 case NC_FLOAT:
71 if(FLT_MAX < X_FLOAT_MAX) {
72 min = (-FLT_MAX);
73 max = FLT_MAX;
74 } else {
75 min = X_FLOAT_MIN;
76 max = X_FLOAT_MAX;
77 }
78 break;
79 case NC_DOUBLE:
80 if(FLT_MAX < X_DOUBLE_MAX) {
81 min = (-FLT_MAX);
82 max = FLT_MAX;
83 } else {
84 min = X_DOUBLE_MIN;
85 max = X_DOUBLE_MAX;
86 }
87 break;
88 case NC_UBYTE: min = 0; max = X_UCHAR_MAX; break;
89 case NC_USHORT: min = 0; max = X_USHORT_MAX; break;
90 case NC_UINT: min = 0; max = X_UINT_MAX; break;
91 case NC_INT64: min = X_INT64_MIN; max = X_INT64_MAX; break;
92 case NC_UINT64: min = 0; max = X_UINT64_MAX; break;
93 default: assert(0);
94 }
95 if(!( value >= min && value <= max)) {
96 #if 0 /* DEBUG */
97 if(xtype == NC_FLOAT) {
98 fprintf(stderr, "\n");
99 fprintf(stderr, "min % .17e\n", min);
100 fprintf(stderr, "value % .17e\n", value);
101 fprintf(stderr, "max % .17e\n", max);
102 }
103 #endif
104 return 0;
105 }
106 #if FLT_MANT_DIG != DBL_MANT_DIG
107 /* else */
108 {
109 const float fvalue = (float)value;
110 return fvalue >= min && fvalue <= max;
111 }
112 #else
113 return 1;
114 #endif
115 }
116
117 /* wrapper for inRange to handle special NC_BYTE/uchar adjustment */
118 /* this function checks whether "value" to be casted to type "itype" is
119 * within the range of external "xtype".
120 */
121 int
inRange3(const int cdf_format,const double value,const nc_type xtype,const nct_itype itype)122 inRange3(const int cdf_format,
123 const double value,
124 const nc_type xtype,
125 const nct_itype itype)
126 {
127 /* netCDF specification make a special case for type conversion between
128 * uchar and NC_BYTE: do not check for range error. See
129 * http://www.unidata.ucar.edu/software/netcdf/docs/data_type.html#type_conversion
130 * The _uchar and _schar functions were introduced in netCDF-3 to eliminate
131 * an ambiguity, and support both signed and unsigned byte data. In
132 * netCDF-2, whether the external NC_BYTE type represented signed or
133 * unsigned values was left up to the user. In netcdf-3, we treat NC_BYTE
134 * as signed for the purposes of conversion to short, int, long, float, or
135 * double. (Of course, no conversion takes place when the internal type is
136 * signed char.) In the _uchar functions, we treat NC_BYTE as if it were
137 * unsigned. Thus, no NC_ERANGE error can occur converting between NC_BYTE
138 * and unsigned char.
139 */
140 switch (itype) {
141 case NCT_UCHAR:
142 return inRange_uchar(cdf_format, value, xtype);
143 case NCT_FLOAT:
144 return inRange_float(value, xtype);
145 default:
146 break;
147 }
148 return inRange(value, xtype);
149 }
150
151
152 /*
153 * Does x == y, where one is internal and other external (netCDF)?
154 * Use tolerant comparison based on IEEE FLT_EPSILON or DBL_EPSILON.
155 */
156 int
equal(const double x,const double y,nc_type xtype,nct_itype itype)157 equal(const double x,
158 const double y,
159 nc_type xtype, /* external data type */
160 nct_itype itype)
161 {
162 const double flt_epsilon = 1.19209290E-07;
163 const double dbl_epsilon = 2.2204460492503131E-16;
164 double epsilon;
165
166 epsilon = xtype == NC_FLOAT ||
167 itype == NCT_FLOAT ? flt_epsilon : dbl_epsilon;
168
169 if (xtype == NC_CHAR && itype == NCT_TEXT) {
170 /* because in-memory data type char can be signed or unsigned,
171 * type cast the value from external NC_CHAR before the comparison
172 */
173 char x2 = (char) x;
174 char y2 = (char) y;
175 return ABS(x2-y2) <= epsilon * MAX( ABS(x2), ABS(y2));
176 }
177
178 return ABS(x-y) <= epsilon * MAX( ABS(x), ABS(y));
179 }
180
181 /* this function is for the APIs without itype, i.e. xtype == itype */
182 int
equal2(const double x,const double y,nc_type xtype)183 equal2(const double x,
184 const double y,
185 nc_type xtype) /* external data type */
186 {
187 const double flt_epsilon = 1.19209290E-07;
188 const double dbl_epsilon = 2.2204460492503131E-16;
189 double epsilon;
190
191 epsilon = xtype == NC_FLOAT ? flt_epsilon : dbl_epsilon;
192
193 if (xtype == NC_CHAR) {
194 /* because in-memory data type char can be signed or unsigned,
195 * type cast the value from external NC_CHAR before the comparison
196 */
197 char x2 = (char) x;
198 char y2 = (char) y;
199 return ABS(x2-y2) <= epsilon * MAX( ABS(x2), ABS(y2));
200 }
201
202 return ABS(x-y) <= epsilon * MAX( ABS(x), ABS(y));
203 }
204
205 /* Test whether two int vectors are equal. If so return 1, else 0 */
206 int
int_vec_eq(const int * v1,const int * v2,const int n)207 int_vec_eq(const int *v1, const int *v2, const int n)
208 {
209 int i;
210 for (i= 0; i < n && v1[i] == v2[i]; i++)
211 ;
212 return i == n;
213 }
214
215
216 /*
217 * Generate random integer from 0 to n-1
218 * Like throwing an n-sided dice marked 0, 1, 2, ..., n-1
219 */
roll(size_t n)220 size_t roll( size_t n )
221 {
222 size_t r;
223
224 do
225 /*
226 * Compute a pseudo-random value between 0.0 and 1.0, multiply
227 * it by n-1, and then find the nearest integer.
228 *
229 * We don't use RAND_MAX here because not all compilation
230 * environments define it (e.g. gcc(1) under SunOS 4.1.4).
231 */
232 r = (size_t)(((rand() % 32768) / 32767.0) * (n - 1) + 0.5);
233 while (r >= n);
234
235 return r;
236 }
237
238
239 /*
240 * Convert number to mixed base
241 *
242 * E.g. to convert 41 inches to yards, feet and inches:
243 * size_t base[] = {1, 3, 12};
244 * size_t result[3];
245 * status = toMixedBase(41, 3, base, result);
246 *
247 * Author: Harvey Davies, Unidata/UCAR, Boulder, Colorado
248 */
249 int
toMixedBase(size_t number,int length,const size_t base[],size_t result[])250 toMixedBase(
251 size_t number, /* number to be converted to mixed base */
252 int length,
253 const size_t base[], /* dimensioned [length], base[0] ignored */
254 size_t result[]) /* dimensioned [length] */
255 {
256 int i;
257
258 if (length > 0) {
259 for (i = length - 1; i > 0; i--) {
260 if (base[i] == 0) return 1;
261 result[i] = number % base[i];
262 number = number / base[i];
263 }
264 result[0] = number;
265 }
266 return 0;
267 }
268
269 /*
270 * Convert number from mixed base
271 *
272 * E.g. to convert 1 yard, 0 feet, 5 inches to inches:
273 * size_t number[] = {1, 0, 5};
274 * size_t base[] = {1, 3, 12};
275 * inches = fromMixedBase(3, number, base);
276 *
277 * Author: Harvey Davies, Unidata/UCAR, Boulder, Colorado
278 */
279 size_t
fromMixedBase(int length,size_t number[],size_t base[])280 fromMixedBase(int length,
281 size_t number[], /* dimensioned [length] */
282 size_t base[]) /* dimensioned [length], base[0] ignored */
283 {
284 size_t i;
285 size_t result = 0;
286
287 for (i = 1; i < length; i++) {
288 result += number[i-1];
289 result *= base[i];
290 }
291 if (length > 0)
292 result += number[i-1];
293 return result;
294 }
295
296
297 /* Convert any nc_type to double */
nc2dbl(const nc_type xtype,const void * p,double * result)298 int nc2dbl ( const nc_type xtype, const void *p, double *result)
299 {
300 if ( ! p ) return 2;
301 if ( ! result ) return 3;
302 switch (xtype) {
303 case NC_CHAR: *result = *((char *) p); break;
304 case NC_BYTE: *result = *((signed char *) p); break;
305 case NC_UBYTE: *result = *((unsigned char *) p); break;
306 case NC_SHORT: *result = *((short *) p); break;
307 case NC_USHORT: *result = *((unsigned short *) p); break;
308 case NC_INT:
309 #if INT_MAX >= X_INT_MAX
310 *result = *((int *) p); break;
311 #else
312 *result = *((long *) p); break;
313 #endif
314 case NC_UINT:
315 #if UINT_MAX >= X_UINT_MAX
316 *result = *((unsigned int *) p); break;
317 #else
318 *result = *((unsigned long *) p); break;
319 #endif
320 case NC_FLOAT: *result = *((float *) p); break;
321 case NC_DOUBLE: *result = *((double *) p); break;
322 case NC_INT64: *result = *((long long *) p); break;
323 case NC_UINT64: *result = *((unsigned long long *) p); break;
324 default: return 1;
325 }
326 return 0;
327 }
328
329
330 /* Convert double to any nc_type */
dbl2nc(const double d,const nc_type xtype,void * p)331 int dbl2nc ( const double d, const nc_type xtype, void *p)
332 {
333 double r; /* rounded value */
334
335 if (p == NULL) return 1;
336 switch (xtype) {
337 case NC_CHAR:
338 r = floor(0.5+d);
339 /* d is obtained from hash() which may be set to X_CHAR_MIN (0)
340 * or X_CHAR_MAX (255). When in-memory data type char is signed
341 * (i.e. ranged from -128 to 127), we should still allow a type
342 * cast a unsigned value > 127 to a signed char without
343 * reporting it as a range error.
344 */
345 if ( r < X_CHAR_MIN || r > X_CHAR_MAX ) return 2;
346 *((signed char*) p) = (signed char)r;
347 break;
348 case NC_BYTE:
349 r = floor(0.5+d);
350 if ( r < schar_min || r > schar_max ) return 2;
351 *((signed char *) p) = (signed char)r;
352 break;
353 case NC_UBYTE:
354 r = floor(0.5+d);
355 if ( r < 0.0 || r > uchar_max ) return 2;
356 *((unsigned char *) p) = (unsigned char)r;
357 break;
358 case NC_SHORT:
359 r = floor(0.5+d);
360 if ( r < short_min || r > short_max ) return 2;
361 *((short *) p) = (short)r;
362 break;
363 case NC_USHORT:
364 r = floor(0.5+d);
365 if ( r < 0.0 || r > ushort_max ) return 2;
366 *((unsigned short *) p) = (unsigned short)r;
367 break;
368 case NC_INT:
369 r = floor(0.5+d);
370 if ( r < long_min || r > long_max ) return 2;
371 #if INT_MAX >= X_INT_MAX
372 *((int *) p) = (int)r;
373 #else
374 *((long *) p) = (long)r;
375 #endif
376 break;
377 case NC_UINT:
378 r = floor(0.5+d);
379 if ( r < 0.0 || r > uint_max ) return 2;
380 #if UINT_MAX >= X_UINT_MAX
381 *((unsigned int *) p) = (unsigned int)r;
382 #else
383 *((unsigned long *) p) = (unsigned long)r;
384 #endif
385 break;
386 case NC_FLOAT:
387 if ( fabs(d) > float_max ) return 2;
388 *((float *) p) = (float)d;
389 break;
390 case NC_DOUBLE:
391 *((double *) p) = (double)d;
392 break;
393 case NC_INT64:
394 r = floor(0.5+d);
395 if ( r < int64_min || r > int64_max ) return 2;
396 *((long long *) p) = (long long)r;
397 break;
398 case NC_UINT64:
399 r = floor(0.5+d);
400 if ( r < 0.0 || r > uint64_max ) return 2;
401 *((unsigned long long *) p) = (unsigned long long)r;
402 break;
403 default:
404 return 1;
405 }
406 return 0;
407 }
408
409 #define FUZZ (1.19209290E-07)
410
411 #ifdef USE_EXTREME_NUMBERS
412 /* Generate data values as function of type, rank (-1 for attribute), index */
413 double
hash(const nc_type xtype,const int rank,const size_t * index)414 hash( const nc_type xtype, const int rank, const size_t *index )
415 {
416 double base;
417 double result;
418 int d; /* index of dimension */
419
420 /* If vector then elements 0 & 1 are min & max. Elements 2 & 3 are */
421 /* just < min & > max (except for NC_CHAR & NC_DOUBLE) */
422 if (abs(rank) == 1 && index[0] <= 3) {
423 switch (index[0]) {
424 case 0:
425 switch (xtype) {
426 case NC_CHAR: return X_CHAR_MIN;
427 case NC_BYTE: return X_BYTE_MIN;
428 case NC_SHORT: return X_SHORT_MIN;
429 case NC_INT: return X_INT_MIN;
430 case NC_FLOAT: return X_FLOAT_MIN;
431 case NC_DOUBLE: return X_DOUBLE_MIN;
432 case NC_UBYTE: return 0;
433 case NC_USHORT: return 0;
434 case NC_UINT: return 0;
435 case NC_INT64: return X_INT_MIN - 128.0; /* slight smaller
436 than INT_MIN */
437 case NC_UINT64: return 0;
438 default: assert(0);
439 }
440 case 1:
441 switch (xtype) {
442 case NC_CHAR: return X_CHAR_MAX;
443 case NC_BYTE: return X_BYTE_MAX;
444 case NC_SHORT: return X_SHORT_MAX;
445 case NC_INT: return X_INT_MAX;
446 case NC_FLOAT: return X_FLOAT_MAX;
447 case NC_DOUBLE: return X_DOUBLE_MAX;
448 case NC_UBYTE: return X_UCHAR_MAX;
449 case NC_USHORT: return X_USHORT_MAX;
450 case NC_UINT: return X_UINT_MAX;
451 case NC_INT64: return X_INT_MAX + 128.0;
452 /* slightly bigger than INT_MAX */
453 case NC_UINT64: return X_UINT_MAX + 128.0;
454 /* slightly bigger than UINT_MAX */
455 default: assert(0);
456 }
457 case 2:
458 switch (xtype) {
459 case NC_CHAR: return 'A';
460 case NC_BYTE: return X_BYTE_MIN-1.0;
461 case NC_SHORT: return X_SHORT_MIN-1.0;
462 case NC_INT: return X_INT_MIN-1.0;
463 case NC_FLOAT: return X_FLOAT_MIN * (1.0 + FUZZ);
464 case NC_DOUBLE: return -1.0;
465 case NC_UBYTE: return -1.0;
466 case NC_USHORT: return -1.0;
467 case NC_UINT: return -1.0;
468 case NC_INT64: return -1.0; /* skip test */
469 case NC_UINT64: return -1.0;
470 default: assert(0);
471 }
472 case 3:
473 switch (xtype) {
474 case NC_CHAR: return 'Z';
475 case NC_BYTE: return X_BYTE_MAX+1.0;
476 case NC_SHORT: return X_SHORT_MAX+1.0;
477 case NC_INT: return X_INT_MAX+1.0;
478 case NC_FLOAT: return X_FLOAT_MAX * (1.0 + FUZZ);
479 case NC_DOUBLE: return 1.0;
480 case NC_UBYTE: return X_UCHAR_MAX +1.0;
481 case NC_USHORT: return X_USHORT_MAX+1.0;
482 case NC_UINT: return X_UINT_MAX +1.0;
483 case NC_INT64: return 1.0; /* skip test */
484 case NC_UINT64: return 1.0; /* skip test */
485 default: assert(0);
486 }
487 }
488 } else {
489 switch (xtype) {
490 case NC_CHAR: base = 2; break;
491 case NC_BYTE: base = -2; break;
492 case NC_SHORT: base = -5; break;
493 case NC_INT: base = -20; break;
494 case NC_FLOAT: base = -9; break;
495 case NC_DOUBLE: base = -10; break;
496
497 /* not sure what right values are */
498 case NC_UBYTE: base = 2; break;
499 case NC_USHORT: base = 5; break;
500 case NC_UINT: base = 20; break;
501 case NC_INT64: base = -20; break;
502 case NC_UINT64: base = 20; break;
503 default: assert(0);
504 }
505 result = rank < 0 ? base * 7 : base * (rank + 1);
506 for (d = 0; d < abs(rank); d++)
507 result = base * (result + index[d]);
508 }
509 return result;
510 }
511 #else /* USE_EXTREME_NUMBERS */
512 #define SANE_SHORT 3333
513 #define SANE_INT 2222
514 #define SANE_FLOAT 300.0
515 #define SANE_DOUBLE 1000.0
516
517 /* Generate data values as function of type, rank (-1 for attribute), index */
518 double
hash(const nc_type xtype,const int rank,const size_t * index)519 hash( const nc_type xtype, const int rank, const size_t *index )
520 {
521 double base;
522 double result;
523 int d; /* index of dimension */
524
525 /* If vector then elements 0 & 1 are min & max. Elements 2 & 3 are */
526 /* just < min & > max (except for NC_CHAR & NC_DOUBLE) */
527 if (abs(rank) == 1 && index[0] <= 3) {
528 switch (index[0]) {
529 case 0:
530 switch (xtype) {
531 case NC_CHAR: return X_CHAR_MIN;
532 case NC_BYTE: return X_BYTE_MIN;
533 case NC_SHORT: return SANE_SHORT;
534 case NC_INT: return SANE_INT;
535 case NC_FLOAT: return SANE_FLOAT;
536 case NC_DOUBLE: return SANE_DOUBLE;
537 case NC_UBYTE: return 0;
538 case NC_USHORT: return 0;
539 case NC_UINT: return 0;
540 case NC_INT64: return X_INT_MIN - 128.0; /* slight smaller
541 than INT_MIN */
542 case NC_UINT64: return 0;
543 default: assert(0);
544 }
545 case 1:
546 switch (xtype) {
547 case NC_CHAR: return X_CHAR_MAX;
548 case NC_BYTE: return X_BYTE_MAX;
549 case NC_SHORT: return SANE_SHORT;
550 case NC_INT: return SANE_INT;
551 case NC_FLOAT: return SANE_FLOAT;
552 case NC_DOUBLE: return SANE_DOUBLE;
553 case NC_UBYTE: return X_UCHAR_MAX;
554 case NC_USHORT: return X_USHORT_MAX;
555 case NC_UINT: return X_UINT_MAX;
556 case NC_INT64: return X_INT_MAX + 128.0;
557 /* slightly bigger than INT_MAX */
558 case NC_UINT64: return X_UINT_MAX + 128.0;
559 /* slightly bigger than UINT_MAX */
560 default: assert(0);
561 }
562 case 2:
563 switch (xtype) {
564 case NC_CHAR: return 'A';
565 case NC_BYTE: return X_BYTE_MIN-1.0;
566 case NC_SHORT: return SANE_SHORT-1.0;
567 case NC_INT: return SANE_INT-1.0;
568 case NC_FLOAT: return SANE_FLOAT * (1.0 + FUZZ);
569 case NC_DOUBLE: return -1.0;
570 case NC_UBYTE: return -1.0;
571 case NC_USHORT: return -1.0;
572 case NC_UINT: return -1.0;
573 case NC_INT64: return -1.0; /* skip test */
574 case NC_UINT64: return -1.0;
575 default: assert(0);
576 }
577 case 3:
578 switch (xtype) {
579 case NC_CHAR: return 'Z';
580 case NC_BYTE: return X_BYTE_MAX+1.0;
581 case NC_SHORT: return SANE_SHORT+1.0;
582 case NC_INT: return SANE_INT+1.0;
583 case NC_FLOAT: return SANE_FLOAT * (1.0 + FUZZ);
584 case NC_DOUBLE: return 1.0;
585 case NC_UBYTE: return X_UCHAR_MAX +1.0;
586 case NC_USHORT: return X_USHORT_MAX+1.0;
587 case NC_UINT: return X_UINT_MAX +1.0;
588 case NC_INT64: return 1.0; /* skip test */
589 case NC_UINT64: return 1.0; /* skip test */
590 default: assert(0);
591 }
592 }
593 } else {
594 switch (xtype) {
595 case NC_CHAR: base = 2; break;
596 case NC_BYTE: base = -2; break;
597 case NC_SHORT: base = -5; break;
598 case NC_INT: base = -20; break;
599 case NC_FLOAT: base = -9; break;
600 case NC_DOUBLE: base = -10; break;
601
602 /* not sure what right values are */
603 case NC_UBYTE: base = 2; break;
604 case NC_USHORT: base = 5; break;
605 case NC_UINT: base = 20; break;
606 case NC_INT64: base = -20; break;
607 case NC_UINT64: base = 20; break;
608 default: assert(0);
609 }
610 result = rank < 0 ? base * 7 : base * (rank + 1);
611 for (d = 0; d < abs(rank); d++)
612 result = base * (result + index[d]);
613 }
614 return result;
615 }
616 #endif
617 /* wrapper for hash to handle special NC_BYTE/uchar adjustment */
618 double
hash4(const int cdf_format,const nc_type xtype,const int rank,const size_t * index,const nct_itype itype)619 hash4(const int cdf_format,
620 const nc_type xtype,
621 const int rank,
622 const size_t *index,
623 const nct_itype itype)
624 {
625 double result;
626
627 result = hash( xtype, rank, index );
628
629 /* netCDF specification make a special case for type conversion between
630 * uchar and NC_BYTE: do not check for range error. See
631 * http://www.unidata.ucar.edu/software/netcdf/docs/data_type.html#type_conversion
632 * The _uchar and _schar functions were introduced in netCDF-3 to eliminate
633 * an ambiguity, and support both signed and unsigned byte data. In
634 * netCDF-2, whether the external NC_BYTE type represented signed or
635 * unsigned values was left up to the user. In netcdf-3, we treat NC_BYTE
636 * as signed for the purposes of conversion to short, int, long, float, or
637 * double. (Of course, no conversion takes place when the internal type is
638 * signed char.) In the _uchar functions, we treat NC_BYTE as if it were
639 * unsigned. Thus, no NC_ERANGE error can occur converting between NC_BYTE
640 * and unsigned char.
641 */
642 if (cdf_format < NC_FORMAT_CDF5 &&
643 itype == NCT_UCHAR && xtype == NC_BYTE &&
644 result >= -128 && result < 0)
645 result += 256;
646
647 return result;
648 }
649
650 static nc_type
char2type(char letter)651 char2type(char letter) {
652 switch (letter) {
653 case 'c': return NC_CHAR;
654 case 'b': return NC_BYTE;
655 case 's': return NC_SHORT;
656 case 'i': return NC_INT;
657 case 'f': return NC_FLOAT;
658 case 'd': return NC_DOUBLE;
659 case 'y': return NC_UBYTE;
660 case 't': return NC_USHORT;
661 case 'u': return NC_UINT;
662 case 'x': return NC_INT64;
663 case 'z': return NC_UINT64;
664 default: assert(0);
665 }
666 return NC_CHAR; /* Just to keep compiler happy */
667 }
668
669
670 static void
init_dims(const char * digit)671 init_dims(const char *digit)
672 {
673 int dimid; /* index of dimension */
674 for (dimid = 0; dimid < NDIMS; dimid++)
675 {
676 dim_len[dimid] = dimid == 0 ? NRECS : dimid;
677 dim_name[dimid][0] = 'D';
678 dim_name[dimid][1] = digit[dimid];
679 dim_name[dimid][2] = '\0';
680 }
681 }
682
683 static void
init_gatts(const char * type_letter)684 init_gatts(const char *type_letter)
685 {
686 int attid;
687 for (attid = 0; attid < numGatts; attid++)
688 {
689 gatt_name[attid][0] = 'G';
690 gatt_name[attid][1] = type_letter[attid];
691 gatt_name[attid][2] = '\0';
692 gatt_len[attid] = 1 + attid;
693 gatt_type[attid] = char2type (type_letter[attid]);
694 }
695 }
696
697 static size_t
product(int nn,const size_t * sp)698 product(int nn, const size_t *sp)
699 {
700 size_t result = 1;
701 while(nn-- > 0)
702 result *= *sp++;
703 return result;
704 }
705
706 /*
707 define global variables:
708 dim_name, dim_len,
709 var_name, var_type, var_rank, var_shape, var_natts, var_dimid, var_nels
710 att_name, gatt_name, att_type, gatt_type, att_len, gatt_len
711 */
712 void
init_gvars(void)713 init_gvars (void)
714 {
715 const size_t max_dim_len[MAX_RANK] = {
716 MAX_DIM_LEN +1,
717 MAX_DIM_LEN,
718 MAX_DIM_LEN
719 };
720 const char type_letter[] = "cbsifdytuxz";
721 /* c:char, b:byte, s:short, i:int, f:float, d:double, y:ubyte, t:ushort,
722 * u:uint, x:int64, z:uint64
723 */
724 const char digit[] = "r123456789";
725
726 int rank;
727 int vn; /* var number */
728 int xtype; /* index of type */
729 int an; /* attribute number */
730
731 assert(sizeof(max_dim_len)/sizeof(max_dim_len[0]) >= MAX_RANK);
732
733 init_dims(digit);
734
735 for (vn=0; vn<numVars; vn++)
736 memset(var_name[vn], 0, 2+MAX_RANK);
737
738 for (rank = 0, vn = 0, xtype = 0, an = 0; rank <= MAX_RANK; rank++)
739 {
740 /* number variables of a type and rank */
741 const size_t nvars = product(rank, max_dim_len);
742 size_t jj;
743
744 for (jj = 0; jj < nvars; jj++)
745 {
746 /* number types of this shape */
747 const int ntypes = rank < 2 ? numTypes : 1;
748
749 int tc;
750 for (tc = 0; tc < ntypes;
751 tc++, vn++, xtype = (xtype + 1) % numTypes)
752 {
753 size_t tmp[MAX_RANK];
754
755 var_name[vn][0] = type_letter[xtype];
756 var_type[vn] = char2type (type_letter[xtype]);
757 var_rank[vn] = rank;
758 var_natts[vn] = rank == 0 ? vn % (MAX_NATTS + 1) : 0;
759 {
760 int ac;
761 for (ac = 0; ac < var_natts[vn]; ac++, an++)
762 {
763 att_name[vn][ac][0] = type_letter[an % numTypes];
764 att_name[vn][ac][1] = '\0';
765 att_len[vn][ac] = an;
766 att_type[vn][ac] = char2type (type_letter[an % numTypes]);
767 }
768 } /* ac block */
769 #ifndef NDEBUG
770 assert(toMixedBase (jj, rank, max_dim_len, tmp) == 0);
771 #else
772 (void) toMixedBase (jj, rank, max_dim_len, tmp);
773 #endif
774 {
775 int dn; /* dimension number */
776 for (dn = 0; dn < rank; dn++)
777 var_dimid[vn][dn] = (int)tmp[dn];
778 for (dn = 0, var_nels[vn] = 1; dn < rank; dn++)
779 {
780 var_dimid[vn][dn] += dn > 0;
781 assert (var_dimid[vn][dn] <= 9);
782 var_name[vn][dn + 1] = digit[var_dimid[vn][dn]];
783 var_shape[vn][dn] = var_dimid[vn][dn] ?
784 var_dimid[vn][dn] : NRECS;
785 var_nels[vn] *= var_shape[vn][dn];
786 }
787 } /* dn block */
788 }
789 }
790 }
791
792 init_gatts(type_letter);
793 }
794
795
796 /* define dims defined by global variables */
797 void
def_dims(int ncid)798 def_dims(int ncid)
799 {
800 int err; /* status */
801 int i;
802 int dimid; /* dimension id */
803
804 for (i = 0; i < NDIMS; i++) {
805 err = nc_def_dim(ncid, dim_name[i], i==0 ? NC_UNLIMITED : dim_len[i],
806 &dimid);
807 IF (err) error("nc_def_dim: %s", nc_strerror(err));
808 }
809 }
810
811
812 /* define vars defined by global variables */
813 void
def_vars(int ncid)814 def_vars(int ncid)
815 {
816 int err; /* status */
817 int i;
818 int var_id;
819
820 for (i = 0; i < numVars; i++) {
821 err = nc_def_var(ncid, var_name[i], var_type[i], var_rank[i],
822 var_dimid[i], &var_id);
823 IF (err) error("nc_def_var: %s", nc_strerror(err));
824 }
825 }
826
827
828 /* put attributes defined by global variables */
829 void
put_atts(int ncid)830 put_atts(int ncid)
831 {
832 int err; /* status */
833 int i;
834 size_t k;
835 int j; /* index of attribute */
836 int allInRange;
837 double att[MAX_NELS];
838 char catt[MAX_NELS];
839
840 for (i = -1; i < numVars; i++) {
841 for (j = 0; j < NATTS(i); j++) {
842 if (ATT_TYPE(i,j) == NC_CHAR) {
843 for (k = 0; k < ATT_LEN(i,j); k++) {
844 catt[k] = (char) hash(ATT_TYPE(i,j), -1, &k);
845 }
846 err = nc_put_att_text(ncid, i, ATT_NAME(i,j),
847 ATT_LEN(i,j), catt);
848 IF (err)
849 error("nc_put_att_text: %s", nc_strerror(err));
850 } else {
851 for (allInRange = 1, k = 0; k < ATT_LEN(i,j); k++) {
852 att[k] = hash(ATT_TYPE(i,j), -1, &k);
853 allInRange = allInRange && inRange(att[k], ATT_TYPE(i,j));
854 }
855 err = nc_put_att_double(ncid, i, ATT_NAME(i,j),
856 ATT_TYPE(i,j), ATT_LEN(i,j), att);
857 if (allInRange) {
858 IF (err)
859 error("nc_put_att_double: %s", nc_strerror(err));
860 } else {
861 IF (err != NC_ERANGE)
862 error("type-conversion range error: status = %d", err);
863 }
864 }
865 }
866 }
867 }
868
869 /* put variables defined by global variables */
870 void
put_vars(int ncid)871 put_vars(int ncid)
872 {
873 size_t start[MAX_RANK];
874 size_t index[MAX_RANK];
875 int err; /* status */
876 int i;
877 size_t j;
878 double value[MAX_NELS];
879 char text[MAX_NELS];
880 int allInRange;
881
882 for (j = 0; j < MAX_RANK; j++)
883 start[j] = 0;
884 for (i = 0; i < numVars; i++) {
885 for (allInRange = 1, j = 0; j < var_nels[i]; j++) {
886 err = toMixedBase(j, var_rank[i], var_shape[i], index);
887 IF (err) error("toMixedBase");
888 if (var_name[i][0] == 'c') {
889 text[j] = (char) hash(var_type[i], var_rank[i], index);
890 } else {
891 value[j] = hash(var_type[i], var_rank[i], index);
892 allInRange = allInRange && inRange(value[j], var_type[i]);
893 }
894 }
895 if (var_name[i][0] == 'c') {
896 err = nc_put_vara_text(ncid, i, start, var_shape[i], text);
897 IF (err)
898 error("nc_put_vara_text: %s", nc_strerror(err));
899 } else {
900 err = nc_put_vara_double(ncid, i, start, var_shape[i], value);
901 if (allInRange) {
902 IF (err)
903 error("nc_put_vara_double: %s", nc_strerror(err));
904 } else {
905 IF (err != NC_ERANGE)
906 error("type-conversion range error: status = %d", err);
907 }
908 }
909 }
910 }
911
912
913 /* Create & write all of specified file using global variables */
914 void
write_file(char * filename)915 write_file(char *filename)
916 {
917 int ncid; /* netCDF id */
918 int err; /* status */
919 err = file_create(filename, NC_CLOBBER, &ncid);
920 IF (err)
921 error("nc_create: %s", nc_strerror(err));
922
923 def_dims(ncid);
924 def_vars(ncid);
925 put_atts(ncid);
926 err = nc_enddef(ncid);
927 IF (err)
928 error("nc_enddef: %s", nc_strerror(err));
929
930 #ifdef USE_PNETCDF
931 err = nc_var_par_access(ncid, NC_GLOBAL, NC_COLLECTIVE);
932 IF (err) error("nc_var_par_access: %s", nc_strerror(err));
933 #endif
934
935 put_vars(ncid);
936
937 err = nc_close (ncid);
938 IF (err)
939 error("nc_close: %s", nc_strerror(err));
940 }
941
942
943 /*
944 * check dimensions of specified file have expected name & length
945 */
946 void
check_dims(int ncid)947 check_dims(int ncid)
948 {
949 char name[NC_MAX_NAME];
950 size_t length;
951 int i;
952 int err; /* status */
953
954 for (i = 0; i < NDIMS; i++) {
955 err = nc_inq_dim(ncid, i, name, &length);
956 IF (err)
957 error("nc_inq_dim: %s", nc_strerror(err));
958 IF (strcmp(name, dim_name[i]) != 0)
959 error("Unexpected name of dimension %d: '%s', expected: '%s'", i, name, dim_name[i]);
960 IF (length != dim_len[i])
961 error("Unexpected length %d of dimension %d, expected %zu", length, i, dim_len[i]);
962 }
963 }
964
965
966 /*
967 * check variables of specified file have expected name, type, shape & values
968 */
969 void
check_vars(int ncid)970 check_vars(int ncid)
971 {
972 size_t index[MAX_RANK];
973 char text, name[NC_MAX_NAME];
974 int i, err; /* status */
975 size_t j;
976 int nok = 0; /* count of valid comparisons */
977 int isChar, ndims, dimids[MAX_RANK];
978 double value, expect;
979 nc_type xtype;
980 size_t length;
981
982 for (i = 0; i < numVars; i++) {
983 isChar = var_type[i] == NC_CHAR;
984 err = nc_inq_var(ncid, i, name, &xtype, &ndims, dimids, NULL);
985 IF (err)
986 error("nc_inq_var: %s", nc_strerror(err));
987 IF (strcmp(name, var_name[i]) != 0)
988 error("Unexpected var_name");
989 IF (xtype != var_type[i])
990 error("Unexpected type");
991 IF (ndims != var_rank[i])
992 error("Unexpected rank");
993 for (j = 0; j < ndims; j++) {
994 err = nc_inq_dim(ncid, dimids[j], 0, &length);
995 IF (err)
996 error("nc_inq_dim: %s", nc_strerror(err));
997 IF (length != var_shape[i][j])
998 error("Unexpected shape");
999 }
1000 for (j = 0; j < var_nels[i]; j++) {
1001 err = toMixedBase(j, var_rank[i], var_shape[i], index);
1002 IF (err)
1003 error("error in toMixedBase 2");
1004 expect = hash( var_type[i], var_rank[i], index );
1005 if (isChar) {
1006 err = nc_get_var1_text(ncid, i, index, &text);
1007 IF (err)
1008 error("nc_get_var1_text: %s", nc_strerror(err));
1009 IF (text != (char)expect) {
1010 error("Var %s [%lu] value read %hhd not that expected %g ",
1011 var_name[i], j, text, expect);
1012 print_n_size_t(var_rank[i], index);
1013 } else {
1014 nok++;
1015 }
1016 } else {
1017 err = nc_get_var1_double(ncid, i, index, &value);
1018 if (inRange(expect,var_type[i])) {
1019 IF (err) {
1020 error("nc_get_var1_double: %s", nc_strerror(err));
1021 } else {
1022 IF (!equal(value,expect,var_type[i], NCT_DOUBLE)) {
1023 error("Var %s [%lu] value read %g not that expected %g ",
1024 var_name[i], j, value, expect);
1025 print_n_size_t(var_rank[i], index);
1026 } else {
1027 nok++;
1028 }
1029 }
1030 }
1031 }
1032 }
1033 }
1034 print_nok(nok);
1035 }
1036
1037
1038 /*
1039 * check attributes of specified file have expected name, type, length & values
1040 */
1041 void
check_atts(int ncid)1042 check_atts(int ncid)
1043 {
1044 int err; /* status */
1045 int i;
1046 int j;
1047 size_t k;
1048 nc_type xtype;
1049 char name[NC_MAX_NAME];
1050 size_t length;
1051 char text[MAX_NELS];
1052 double value[MAX_NELS];
1053 double expect;
1054 int nok = 0; /* count of valid comparisons */
1055
1056 for (i = -1; i < numVars; i++) {
1057 for (j = 0; j < NATTS(i); j++) {
1058 err = nc_inq_attname(ncid, i, j, name);
1059 IF (err)
1060 error("nc_inq_attname: %s", nc_strerror(err));
1061 IF (strcmp(name, ATT_NAME(i,j)) != 0)
1062 error("nc_inq_attname: unexpected name");
1063 err = nc_inq_att(ncid, i, name, &xtype, &length);
1064 IF (err)
1065 error("nc_inq_att: %s", nc_strerror(err));
1066 IF (xtype != ATT_TYPE(i,j))
1067 error("nc_inq_att: unexpected type");
1068 IF (length != ATT_LEN(i,j))
1069 error("nc_inq_att: unexpected length");
1070 if (xtype == NC_CHAR) {
1071 err = nc_get_att_text(ncid, i, name, text);
1072 IF (err)
1073 error("nc_get_att_text: %s", nc_strerror(err));
1074 for (k = 0; k < ATT_LEN(i,j); k++) {
1075 expect = hash(xtype, -1, &k);
1076 IF (text[k] != (char)expect) {
1077 error("nc_get_att_text: unexpected value");
1078 } else {
1079 nok++;
1080 }
1081 }
1082 } else {
1083 err = nc_get_att_double(ncid, i, name, value);
1084 for (k = 0; k < ATT_LEN(i,j); k++) {
1085 expect = hash(xtype, -1, &k);
1086 if (inRange(expect,ATT_TYPE(i,j))) {
1087 IF (err)
1088 error("nc_get_att_double: %s", nc_strerror(err));
1089 IF (!equal(value[k], expect, ATT_TYPE(i,j), NCT_DOUBLE)) {
1090 error("Att value read not that expected");
1091 } else {
1092 nok++;
1093 }
1094 }
1095 }
1096 }
1097 }
1098 }
1099 print_nok(nok);
1100 }
1101
1102
1103 /* Check file (dims, vars, atts) corresponds to global variables */
1104 void
check_file(char * filename)1105 check_file(char *filename)
1106 {
1107 int ncid; /* netCDF id */
1108 int err; /* status */
1109
1110 err = file_open(filename, NC_NOWRITE, &ncid);
1111 IF (err) {
1112 error("nc_open: %s", nc_strerror(err));
1113 } else {
1114 check_dims(ncid);
1115 check_vars(ncid);
1116 check_atts(ncid);
1117 err = nc_close (ncid);
1118 IF (err)
1119 error("nc_close: %s", nc_strerror(err));
1120 }
1121 }
1122
1123 /* TODO: Maybe this function belongs in the netcdf library. */
1124 const char *
s_nc_type(nc_type xtype)1125 s_nc_type(nc_type xtype)
1126 {
1127 switch((int)xtype){
1128 case NC_CHAR: return "NC_CHAR";
1129 case NC_BYTE: return "NC_BYTE";
1130 case NC_UBYTE: return "NC_UBYTE";
1131 case NC_SHORT: return "NC_SHORT";
1132 case NC_USHORT: return "NC_USHORT";
1133 case NC_INT: return "NC_INT";
1134 case NC_UINT: return "NC_UINT";
1135 case NC_FLOAT: return "NC_FLOAT";
1136 case NC_DOUBLE: return "NC_DOUBLE";
1137 case NC_INT64: return "NC_INT64";
1138 case NC_UINT64: return "NC_UINT64";
1139 }
1140 return "";
1141 }
1142
1143
file_create(const char * filename,int cmode,int * ncid)1144 int file_create(const char *filename, int cmode, int *ncid)
1145 {
1146 int err;
1147
1148 #ifdef USE_PNETCDF
1149 /* get the default file format */
1150 int default_format;
1151 nc_set_default_format(NC_FORMAT_CLASSIC, &default_format);
1152 /* set it back to the default */
1153 nc_set_default_format(default_format, NULL);
1154
1155 if (default_format == NC_FORMAT_CLASSIC ||
1156 default_format == NC_FORMAT_64BIT_OFFSET ||
1157 default_format == NC_FORMAT_64BIT_DATA)
1158 err = nc_create_par(filename, cmode, MPI_COMM_WORLD, MPI_INFO_NULL, ncid);
1159 else
1160 #endif
1161 err = nc_create(filename, cmode, ncid);
1162
1163 return err;
1164 }
1165
file__create(const char * filename,int cmode,size_t initialsz,size_t * bufrsizehintp,int * ncid)1166 int file__create(const char *filename,
1167 int cmode,
1168 size_t initialsz,
1169 size_t *bufrsizehintp,
1170 int *ncid)
1171 {
1172 int err;
1173
1174 #ifdef USE_PNETCDF
1175 /* get the default file format */
1176 int default_format;
1177 err = nc_set_default_format(NC_FORMAT_CLASSIC, &default_format);
1178 /* set it back to the default */
1179 err = nc_set_default_format(default_format, NULL);
1180
1181 if (default_format == NC_FORMAT_CLASSIC ||
1182 default_format == NC_FORMAT_64BIT_OFFSET ||
1183 default_format == NC_FORMAT_64BIT_DATA)
1184 err = nc_create_par(filename, cmode, MPI_COMM_WORLD, MPI_INFO_NULL, ncid);
1185 else
1186 #endif
1187 err = nc__create(filename, cmode, initialsz, bufrsizehintp, ncid);
1188
1189 return err;
1190 }
1191
file_open(const char * filename,int omode,int * ncid)1192 int file_open(const char *filename, int omode, int *ncid)
1193 {
1194 int err;
1195
1196 #ifdef USE_PNETCDF
1197 /* get the default file format */
1198 int default_format;
1199 err = nc_set_default_format(NC_FORMAT_CLASSIC, &default_format);
1200 /* set it back to the default */
1201 err = nc_set_default_format(default_format, NULL);
1202
1203 if (default_format == NC_FORMAT_CLASSIC ||
1204 default_format == NC_FORMAT_64BIT_OFFSET ||
1205 default_format == NC_FORMAT_64BIT_DATA)
1206 err = nc_open_par(filename, omode, MPI_COMM_WORLD, MPI_INFO_NULL, ncid);
1207 else
1208 #endif
1209 err = nc_open(filename, omode, ncid);
1210
1211 return err;
1212 }
1213
1214
1215 #ifdef USE_PNETCDF
1216 #include <pnetcdf.h> /* to include PnetCDF error codes */
1217 #endif
1218
nc_err_code_name(int err)1219 char* nc_err_code_name(int err)
1220 {
1221 static char unknown_str[32];
1222
1223 if (err > 0) { /* system error */
1224 const char *cp = (const char *) strerror(err);
1225 if (cp == NULL)
1226 sprintf(unknown_str,"Unknown error code %d",err);
1227 else
1228 sprintf(unknown_str,"Error code %d (%s)",err,cp);
1229 return unknown_str;
1230 }
1231
1232 switch (err) {
1233 case (NC_NOERR): return "NC_NOERR";
1234 case (NC_EBADID): return "NC_EBADID";
1235 case (NC_ENFILE): return "NC_ENFILE";
1236 case (NC_EEXIST): return "NC_EEXIST";
1237 case (NC_EINVAL): return "NC_EINVAL";
1238 case (NC_EPERM): return "NC_EPERM";
1239 case (NC_ENOTINDEFINE): return "NC_ENOTINDEFINE";
1240 case (NC_EINDEFINE): return "NC_EINDEFINE";
1241 case (NC_EINVALCOORDS): return "NC_EINVALCOORDS";
1242 case (NC_EMAXDIMS): return "NC_EMAXDIMS"; /* not enforced after 4.5.0 */
1243 case (NC_ENAMEINUSE): return "NC_ENAMEINUSE";
1244 case (NC_ENOTATT): return "NC_ENOTATT";
1245 case (NC_EMAXATTS): return "NC_EMAXATTS"; /* not enforced after 4.5.0 */
1246 case (NC_EBADTYPE): return "NC_EBADTYPE";
1247 case (NC_EBADDIM): return "NC_EBADDIM";
1248 case (NC_EUNLIMPOS): return "NC_EUNLIMPOS";
1249 case (NC_EMAXVARS): return "NC_EMAXVARS"; /* not enforced after 4.5.0 */
1250 case (NC_ENOTVAR): return "NC_ENOTVAR";
1251 case (NC_EGLOBAL): return "NC_EGLOBAL";
1252 case (NC_ENOTNC): return "NC_ENOTNC";
1253 case (NC_ESTS): return "NC_ESTS";
1254 case (NC_EMAXNAME): return "NC_EMAXNAME";
1255 case (NC_EUNLIMIT): return "NC_EUNLIMIT";
1256 case (NC_ENORECVARS): return "NC_ENORECVARS";
1257 case (NC_ECHAR): return "NC_ECHAR";
1258 case (NC_EEDGE): return "NC_EEDGE";
1259 case (NC_ESTRIDE): return "NC_ESTRIDE";
1260 case (NC_EBADNAME): return "NC_EBADNAME";
1261 case (NC_ERANGE): return "NC_ERANGE";
1262 case (NC_ENOMEM): return "NC_ENOMEM";
1263 case (NC_EVARSIZE): return "NC_EVARSIZE";
1264 case (NC_EDIMSIZE): return "NC_EDIMSIZE";
1265 case (NC_ETRUNC): return "NC_ETRUNC";
1266 case (NC_EAXISTYPE): return "NC_EAXISTYPE";
1267 case (NC_EDAP): return "NC_EDAP";
1268 case (NC_ECURL): return "NC_ECURL";
1269 case (NC_EIO): return "NC_EIO";
1270 case (NC_ENODATA): return "NC_ENODATA";
1271 case (NC_EDAPSVC): return "NC_EDAPSVC";
1272 case (NC_EDAS): return "NC_EDAS";
1273 case (NC_EDDS): return "NC_EDDS";
1274 case (NC_EDATADDS): return "NC_EDATADDS";
1275 case (NC_EDAPURL): return "NC_EDAPURL";
1276 case (NC_EDAPCONSTRAINT): return "NC_EDAPCONSTRAINT";
1277 case (NC_ETRANSLATION): return "NC_ETRANSLATION";
1278 case (NC_EACCESS): return "NC_EACCESS";
1279 case (NC_EAUTH): return "NC_EAUTH";
1280 case (NC_ENOTFOUND): return "NC_ENOTFOUND";
1281 case (NC_ECANTREMOVE): return "NC_ECANTREMOVE";
1282 case (NC_EINTERNAL): return "NC_EINTERNAL";
1283 case (NC_EPNETCDF): return "NC_EPNETCDF";
1284 case (NC_EHDFERR): return "NC_EHDFERR";
1285 case (NC_ECANTREAD): return "NC_ECANTREAD";
1286 case (NC_ECANTWRITE): return "NC_ECANTWRITE";
1287 case (NC_ECANTCREATE): return "NC_ECANTCREATE";
1288 case (NC_EFILEMETA): return "NC_EFILEMETA";
1289 case (NC_EDIMMETA): return "NC_EDIMMETA";
1290 case (NC_EATTMETA): return "NC_EATTMETA";
1291 case (NC_EVARMETA): return "NC_EVARMETA";
1292 case (NC_ENOCOMPOUND): return "NC_ENOCOMPOUND";
1293 case (NC_EATTEXISTS): return "NC_EATTEXISTS";
1294 case (NC_ENOTNC4): return "NC_ENOTNC4";
1295 case (NC_ESTRICTNC3): return "NC_ESTRICTNC3";
1296 case (NC_ENOTNC3): return "NC_ENOTNC3";
1297 case (NC_ENOPAR): return "NC_ENOPAR";
1298 case (NC_EPARINIT): return "NC_EPARINIT";
1299 case (NC_EBADGRPID): return "NC_EBADGRPID";
1300 case (NC_EBADTYPID): return "NC_EBADTYPID";
1301 case (NC_ETYPDEFINED): return "NC_ETYPDEFINED";
1302 case (NC_EBADFIELD): return "NC_EBADFIELD";
1303 case (NC_EBADCLASS): return "NC_EBADCLASS";
1304 case (NC_EMAPTYPE): return "NC_EMAPTYPE";
1305 case (NC_ELATEFILL): return "NC_ELATEFILL";
1306 case (NC_ELATEDEF): return "NC_ELATEDEF";
1307 case (NC_EDIMSCALE): return "NC_EDIMSCALE";
1308 case (NC_ENOGRP): return "NC_ENOGRP";
1309 case (NC_ESTORAGE): return "NC_ESTORAGE";
1310 case (NC_EBADCHUNK): return "NC_EBADCHUNK";
1311 case (NC_ENOTBUILT): return "NC_ENOTBUILT";
1312 case (NC_EDISKLESS): return "NC_EDISKLESS";
1313 case (NC_ECANTEXTEND): return "NC_ECANTEXTEND";
1314 case (NC_EMPI): return "NC_EMPI";
1315 case (NC_ENULLPAD): return "NC_NULLPAD";
1316 case (NC_EINMEMORY): return "NC_EINMEMORY";
1317 #if 0
1318 case (NC_EURL): return "NC_EURL";
1319 case (NC_ECONSTRAINT): return "NC_ECONSTRAINT";
1320 #endif
1321 #ifdef USE_PNETCDF
1322 case (NC_ESMALL): return "NC_ESMALL";
1323 case (NC_ENOTINDEP): return "NC_ENOTINDEP";
1324 case (NC_EINDEP): return "NC_EINDEP";
1325 case (NC_EFILE): return "NC_EFILE";
1326 case (NC_EREAD): return "NC_EREAD";
1327 case (NC_EWRITE): return "NC_EWRITE";
1328 case (NC_EOFILE): return "NC_EOFILE";
1329 case (NC_EMULTITYPES): return "NC_EMULTITYPES";
1330 case (NC_EIOMISMATCH): return "NC_EIOMISMATCH";
1331 case (NC_ENEGATIVECNT): return "NC_ENEGATIVECNT";
1332 case (NC_EUNSPTETYPE): return "NC_EUNSPTETYPE";
1333 case (NC_EINVAL_REQUEST): return "NC_EINVAL_REQUEST";
1334 case (NC_EAINT_TOO_SMALL): return "NC_EAINT_TOO_SMALL";
1335 case (NC_ENOENT): return "NC_ENOENT";
1336 #ifdef NC_EMULTIDEFINE
1337 case (NC_EMULTIDEFINE): return "NC_EMULTIDEFINE";
1338 #endif
1339 #if PNETCDF_VERSION_MAJOR>=1 && PNETCDF_VERSION_MINOR>=3
1340 case (NC_ENOTSUPPORT): return "NC_ENOTSUPPORT";
1341 case (NC_ENULLBUF): return "NC_ENULLBUF";
1342 case (NC_EPREVATTACHBUF): return "NC_EPREVATTACHBUF";
1343 case (NC_ENULLABUF): return "NC_ENULLABUF";
1344 case (NC_EPENDINGBPUT): return "NC_EPENDINGBPUT";
1345 case (NC_EINSUFFBUF): return "NC_EINSUFFBUF";
1346 #endif
1347 #if PNETCDF_VERSION_MAJOR>=1 && PNETCDF_VERSION_MINOR>=4
1348 case (NC_EINTOVERFLOW): return "NC_EINTOVERFLOW";
1349 case (NC_EMULTIDEFINE_OMODE): return "NC_EMULTIDEFINE_OMODE";
1350 case (NC_EMULTIDEFINE_DIM_NUM): return "NC_EMULTIDEFINE_DIM_NUM";
1351 case (NC_EMULTIDEFINE_DIM_SIZE): return "NC_EMULTIDEFINE_DIM_SIZE";
1352 case (NC_EMULTIDEFINE_DIM_NAME): return "NC_EMULTIDEFINE_DIM_NAME";
1353 case (NC_EMULTIDEFINE_VAR_NUM): return "NC_EMULTIDEFINE_VAR_NUM";
1354 case (NC_EMULTIDEFINE_VAR_NAME): return "NC_EMULTIDEFINE_VAR_NAME";
1355 case (NC_EMULTIDEFINE_VAR_NDIMS): return "NC_EMULTIDEFINE_VAR_NDIMS";
1356 case (NC_EMULTIDEFINE_VAR_DIMIDS): return "NC_EMULTIDEFINE_VAR_DIMIDS";
1357 case (NC_EMULTIDEFINE_VAR_TYPE): return "NC_EMULTIDEFINE_VAR_TYPE";
1358 case (NC_EMULTIDEFINE_VAR_LEN): return "NC_EMULTIDEFINE_VAR_LEN";
1359 case (NC_EMULTIDEFINE_NUMRECS): return "NC_EMULTIDEFINE_NUMRECS";
1360 case (NC_EMULTIDEFINE_VAR_BEGIN): return "NC_EMULTIDEFINE_VAR_BEGIN";
1361 case (NC_EMULTIDEFINE_ATTR_NUM): return "NC_EMULTIDEFINE_ATTR_NUM";
1362 case (NC_EMULTIDEFINE_ATTR_SIZE): return "NC_EMULTIDEFINE_ATTR_SIZE";
1363 case (NC_EMULTIDEFINE_ATTR_NAME): return "NC_EMULTIDEFINE_ATTR_NAME";
1364 case (NC_EMULTIDEFINE_ATTR_TYPE): return "NC_EMULTIDEFINE_ATTR_TYPE";
1365 case (NC_EMULTIDEFINE_ATTR_LEN): return "NC_EMULTIDEFINE_ATTR_LEN";
1366 case (NC_EMULTIDEFINE_ATTR_VAL): return "NC_EMULTIDEFINE_ATTR_VAL";
1367 #endif
1368 #if PNETCDF_VERSION_MAJOR>=1 && PNETCDF_VERSION_MINOR>=5
1369 case (NC_ENOTENABLED): return "NC_ENOTENABLED";
1370 case (NC_EBAD_FILE): return "NC_EBAD_FILE";
1371 case (NC_ENO_SPACE): return "NC_ENO_SPACE";
1372 case (NC_EQUOTA): return "NC_EQUOTA";
1373 case (NC_EMULTIDEFINE_FNC_ARGS): return "NC_EMULTIDEFINE_FNC_ARGS";
1374 #endif
1375 #if PNETCDF_VERSION_MAJOR>=1 && PNETCDF_VERSION_MINOR>=6
1376 case (NC_EINVAL_CMODE): return "NC_EINVAL_CMODE";
1377 case (NC_ENULLSTART): return "NC_ENULLSTART";
1378 case (NC_ENULLCOUNT): return "NC_ENULLCOUNT";
1379 case (NC_ETYPESIZE_MISMATCH): return "NC_ETYPESIZE_MISMATCH";
1380 case (NC_ETYPESIZE): return "NC_ETYPESIZE";
1381 case (NC_ETYPE_MISMATCH): return "NC_ETYPE_MISMATCH";
1382 case (NC_ESTRICTCDF2): return "NC_ESTRICTCDF2";
1383 #endif
1384 #if PNETCDF_VERSION_MAJOR>=1 && PNETCDF_VERSION_MINOR>=7
1385 case (NC_ENOTRECVAR): return "NC_ENOTRECVAR";
1386 case (NC_ENOTFILL): return "NC_ENOTFILL";
1387 case (NC_EMULTIDEFINE_FILL_MODE): return "NC_EMULTIDEFINE_FILL_MODE";
1388 case (NC_EMULTIDEFINE_VAR_FILL_MODE): return "NC_EMULTIDEFINE_VAR_FILL_MODE";
1389 case (NC_EMULTIDEFINE_VAR_FILL_VALUE): return "NC_EMULTIDEFINE_VAR_FILL_VALUE";
1390 #endif
1391 #if PNETCDF_VERSION_MAJOR>=1 && PNETCDF_VERSION_MINOR>=8
1392 case (NC_EPENDING): return "NC_EPENDING";
1393 case (NC_EINVAL_OMODE): return "NC_EINVAL_OMODE";
1394 case (NC_EMULTIDEFINE_CMODE): return "NC_EMULTIDEFINE_CMODE";
1395 #endif
1396 #endif
1397 default:
1398 sprintf(unknown_str,"Unknown code %d",err);
1399 }
1400 return unknown_str;
1401 }
1402
1403
1404 int
test_nc_against_pnetcdf(void)1405 test_nc_against_pnetcdf(void)
1406 {
1407 int format;
1408
1409 nc_set_default_format(NC_FORMAT_CLASSIC, &format);
1410 nc_set_default_format(format, NULL); /* restore default */
1411 if (format == NC_FORMAT_NETCDF4 || format == NC_FORMAT_NETCDF4_CLASSIC)
1412 return 1; /* skip test for netcdf4 formats */
1413
1414 #ifdef USE_PNETCDF
1415 int ncid; /* netCDF id */
1416 int err; /* status */
1417
1418 /* Using netCDF library to create file */
1419 err = nc_create(scratch, NC_CLOBBER, &ncid);
1420 IF (err != NC_NOERR) error("nc_create: %s", nc_strerror(err));
1421 def_dims(ncid);
1422 def_vars(ncid);
1423 put_atts(ncid);
1424 err = nc_enddef(ncid);
1425 IF (err != NC_NOERR) error("nc_enddef: %s", nc_strerror(err));
1426 put_vars(ncid);
1427 err = nc_close (ncid);
1428 IF (err != NC_NOERR) error("nc_close: %s", nc_strerror(err));
1429
1430 /* Using PnetCDF library to check file */
1431 err = nc_open_par(scratch, NC_NOWRITE, MPI_COMM_WORLD, MPI_INFO_NULL, &ncid);
1432 IF (err != NC_NOERR) error("nc_open_par: %s", nc_strerror(err));
1433 check_dims(ncid);
1434 check_vars(ncid);
1435 check_atts(ncid);
1436 err = nc_close (ncid);
1437 IF (err != NC_NOERR) error("nc_close: %s", nc_strerror(err));
1438
1439 /* Using PnetCDF library to create file */
1440 err = nc_create_par(scratch, 0, MPI_COMM_WORLD, MPI_INFO_NULL, &ncid);
1441 IF (err != NC_NOERR) error("nc_create_par: %s", nc_strerror(err));
1442 def_dims(ncid);
1443 def_vars(ncid);
1444 put_atts(ncid);
1445 err = nc_enddef(ncid);
1446 IF (err != NC_NOERR) error("nc_enddef: %s", nc_strerror(err));
1447 put_vars(ncid);
1448 err = nc_close (ncid);
1449 IF (err != NC_NOERR) error("nc_close: %s", nc_strerror(err));
1450
1451 /* Using NetCDF library to check file */
1452 err = nc_open(scratch, NC_NOWRITE, &ncid);
1453 IF (err != NC_NOERR) error("nc_open: %s", nc_strerror(err));
1454 check_dims(ncid);
1455 check_vars(ncid);
1456 check_atts(ncid);
1457 err = nc_close (ncid);
1458 IF (err != NC_NOERR) error("nc_close: %s", nc_strerror(err));
1459 err = nc_delete(scratch);
1460 IF (err != NC_NOERR) error("remove of %s failed", scratch);
1461 #endif
1462 return 1;
1463 }
1464