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