PageRenderTime 46ms CodeModel.GetById 15ms RepoModel.GetById 0ms app.codeStats 1ms

/other/netcdf_write_matrix/src/nctest/vardef.c

http://github.com/jbeezley/wrf-fire
C | 351 lines | 300 code | 21 blank | 30 comment | 79 complexity | d973855f478de11f4b105562a9ddee83 MD5 | raw file
Possible License(s): AGPL-1.0
  1. /*********************************************************************
  2. * Copyright 1993, UCAR/Unidata
  3. * See netcdf/COPYRIGHT file for copying and redistribution conditions.
  4. * $Header: /upc/share/CVS/netcdf-3/nctest/vardef.c,v 1.16 2005/03/17 14:59:18 ed Exp $
  5. *********************************************************************/
  6. #include <stdio.h>
  7. #include <string.h>
  8. #include <stdlib.h> /* for free() */
  9. #ifndef NO_FLOAT_H
  10. #include <float.h> /* for FLT_EPSILON, DBL_EPSILON */
  11. #endif /* NO_FLOAT_H */
  12. #include <netcdf.h>
  13. #include "testcdf.h" /* defines in-memory test cdf structure */
  14. #include "emalloc.h"
  15. #include "add.h" /* functions to update in-memory netcdf */
  16. #include "error.h"
  17. #include "tests.h"
  18. #define LEN_OF(array) ((sizeof array) / (sizeof array[0]))
  19. static float float_eps;
  20. static double double_eps;
  21. static float
  22. float_epsilon()
  23. {
  24. float float_eps;
  25. #ifndef NO_FLOAT_H
  26. float_eps = FLT_EPSILON;
  27. #else /* NO_FLOAT_H */
  28. {
  29. float etop, ebot, eps;
  30. float one = 1.0;
  31. float two = 2.0;
  32. etop = 1.0;
  33. ebot = 0.0;
  34. eps = ebot + (etop - ebot)/two;
  35. while (eps != ebot && eps != etop) {
  36. float epsp1;
  37. epsp1 = one + eps;
  38. if (epsp1 > one)
  39. etop = eps;
  40. else
  41. ebot = eps;
  42. eps = ebot + (etop - ebot)/two;
  43. }
  44. float_eps = two * etop;
  45. }
  46. #endif /* NO_FLOAT_H */
  47. return float_eps;
  48. }
  49. static double
  50. double_epsilon()
  51. {
  52. double double_eps;
  53. #ifndef NO_FLOAT_H
  54. double_eps = DBL_EPSILON;
  55. #else /* NO_FLOAT_H */
  56. {
  57. double etop, ebot, eps;
  58. double one = 1.0;
  59. double two = 2.0;
  60. etop = 1.0;
  61. ebot = 0.0;
  62. eps = ebot + (etop - ebot)/two;
  63. while (eps != ebot && eps != etop) {
  64. double epsp1;
  65. epsp1 = one + eps;
  66. if (epsp1 > one)
  67. etop = eps;
  68. else
  69. ebot = eps;
  70. eps = ebot + (etop - ebot)/two;
  71. }
  72. double_eps = two * etop;
  73. }
  74. #endif /* NO_FLOAT_H */
  75. return double_eps;
  76. }
  77. static void
  78. init_epsilons()
  79. {
  80. float_eps = float_epsilon();
  81. double_eps = double_epsilon();
  82. }
  83. /*
  84. * Test ncvardef
  85. * check that proper define worked with ncvarinq
  86. * check that returned id is one more than previous id
  87. * try redefining an existing variable, check error
  88. * try adding scalar variable (no dimensions)
  89. * try with bad datatype, check error
  90. * try with bad number of dimensions, check error
  91. * try with bad dimension ids, check error
  92. * try in data mode, check error
  93. */
  94. int
  95. test_ncvardef(path)
  96. const char *path; /* name of writable netcdf file to open */
  97. {
  98. int nerrs = 0;
  99. int cdfid; /* netcdf id */
  100. static char pname[] = "test_ncvardef";
  101. int id, iv;
  102. static struct cdfvar va[] = { /* variables of all shapes and sizes */
  103. {"bytev", NC_BYTE, 6, ___, 0},
  104. {"charv", NC_CHAR, 5, ___, 0},
  105. {"shortv", NC_SHORT, 4, ___, 0},
  106. {"longv", NC_LONG, 3, ___, 0},
  107. {"floatv", NC_FLOAT, 2, ___, 0},
  108. {"doublev", NC_DOUBLE, 1, ___, 0},
  109. {"scalarv", NC_DOUBLE, 0, ___, 0}
  110. };
  111. int nv = LEN_OF(va); /* number of variables to define */
  112. int va_id[LEN_OF(va)]; /* variable ids */
  113. static struct cdfvar tmp = /* variable for testing bad types, etc. */
  114. {"tmpv", NC_DOUBLE, 1, ___, 0};
  115. /* if d5 >= 91 in following, problem on machines with 16-bit ints ??? */
  116. static struct cdfdim di[] = { /* a bunch of dimensions */
  117. {"d0", 2}, {"d1",3}, {"d2",5}, {"d3", 6}, {"d4", 4}, {"d5", 31}};
  118. int nd = LEN_OF(di); /* number of dimensions */
  119. int di_id[LEN_OF(di)]; /* dimension ids */
  120. (void) fprintf(stderr, "*** Testing %s ...\t", &pname[5]);
  121. init_epsilons();
  122. if ((cdfid = ncopen(path, NC_WRITE)) == -1) {
  123. error("%s: ncopen failed", pname);
  124. return ++nerrs;
  125. }
  126. /* opened, defining a variable should fail in data mode */
  127. if (ncvardef(cdfid, va[0].name, va[0].type, va[0].ndims, va[0].dims)
  128. != -1) {
  129. error("%s: ncvardef should have failed in data mode", pname);
  130. ncclose(cdfid); return ++nerrs;
  131. }
  132. /* enter define mode */
  133. if (ncredef(cdfid) == -1) {
  134. error("%s: cdredef failed", pname);
  135. ncclose(cdfid); return ++nerrs;
  136. }
  137. /* Add nd more dimensions */
  138. for (id = 0; id < nd; id++) {
  139. if ((di_id[id] = ncdimdef(cdfid, di[id].name, di[id].size)) == -1) {
  140. error("%s: ncdimdef failed for %s, size %d",
  141. pname, di[id].name, di[id].size);
  142. ncclose(cdfid); return ++nerrs;
  143. }
  144. add_dim(&test, &di[id]); /* keep in-memory netcdf in sync */
  145. }
  146. tmp.dims = (int *) emalloc(sizeof(int) * MAX_VAR_DIMS);
  147. tmp.name = (char *) emalloc(MAX_NC_NAME);
  148. /* in define mode, add variables of each type with various shapes */
  149. for (iv = 0; iv < nv; iv++) {
  150. /* set shape to use subset of dimensions previously defined */
  151. va[iv].dims = (int *) emalloc(sizeof(int) * va[iv].ndims);
  152. for (id = 0; id < va[iv].ndims; id++)
  153. va[iv].dims[id] = di_id[id];
  154. if ((va_id[iv] = ncvardef(cdfid, va[iv].name, va[iv].type,
  155. va[iv].ndims, va[iv].dims)) == -1) {
  156. error("%s: ncvardef failed", pname);
  157. errvar(&test,&va[iv]); /* prints details about variable */
  158. ncclose(cdfid); return ++nerrs;
  159. }
  160. add_var(&test, &va[iv]); /* keep in-memory netcdf in sync */
  161. /* check that var id returned is one more than previous var id */
  162. if (va_id[iv] != test.nvars - 1) {
  163. error("%s: ncvardef returned %d for var id, expected %d",
  164. pname, va_id[iv], test.nvars-1);
  165. ncclose(cdfid); return ++nerrs;
  166. }
  167. /* use ncvarinq to get values just set and compare values */
  168. if (ncvarinq(cdfid, va_id[iv], tmp.name, &tmp.type,
  169. &tmp.ndims, tmp.dims, &tmp.natts) == -1) {
  170. error("%s: ncvarinq failed", pname);
  171. errvar(&test,&va[iv]); /* prints details about variable */
  172. ncclose(cdfid); return ++nerrs;
  173. }
  174. if (strcmp(tmp.name, va[iv].name) != 0 ||
  175. tmp.type != va[iv].type ||
  176. tmp.ndims != va[iv].ndims ||
  177. tmp.natts != va[iv].natts) {
  178. error("%s: ncvardef and ncvarinq don't agree for %s",
  179. pname, va[iv].name);
  180. nerrs++;
  181. errvar(&test,&va[iv]);
  182. errvar(&test,&tmp);
  183. }
  184. for (id = 0; id < va[iv].ndims; id++) {
  185. if (tmp.dims[id] != va[iv].dims[id]) {
  186. error("%s: ncvardef and ncvarinq don't agree on shape of %s",
  187. pname, va[iv].name);
  188. nerrs++;
  189. errvar(&test,&va[iv]);
  190. errvar(&test,&tmp);
  191. }
  192. }
  193. }
  194. /* try adding same variable again, this should fail */
  195. if (ncvardef(cdfid, va[0].name, va[0].type,
  196. va[0].ndims, va[0].dims) != -1) {
  197. error("%s: ncvardef should not allow redefinition", pname);
  198. ncclose(cdfid); return ++nerrs;
  199. }
  200. /* try bad type, should fail */
  201. if (ncvardef(cdfid, "badtype", BAD_TYPE, va[0].ndims, va[0].dims) != -1) {
  202. error("%s: ncvardef should have failed on bad type", pname);
  203. ncclose(cdfid); return ++nerrs;
  204. }
  205. /* try bad ndims, should fail */
  206. if (ncvardef(cdfid, "badndims", va[0].type, -1, va[0].dims) != -1) {
  207. error("%s: ncvardef should have failed on bad ndims", pname);
  208. ncclose(cdfid); return ++nerrs;
  209. }
  210. /* try bad ids in dims vector, should fail */
  211. id = va[0].dims[0];
  212. va[0].dims[va[0].ndims-1] = -1;
  213. if (ncvardef(cdfid, "baddims", va[0].type, va[0].ndims, va[0].dims)
  214. != -1) {
  215. error("%s: ncvardef should have failed on negative dim id in dims",
  216. pname);
  217. ncclose(cdfid); return ++nerrs;
  218. }
  219. if (ncendef (cdfid) == -1) {
  220. error("%s: ncendef failed", pname);
  221. ncclose(cdfid); return ++nerrs;
  222. }
  223. /* try reading a value of each type, should get appropriate fill value */
  224. for (iv = 0; iv < nv; iv++) {
  225. static long where[] = {0,0,0,0,0,0};
  226. switch(va[iv].type) {
  227. case NC_BYTE:
  228. {
  229. char val, fillval = FILL_BYTE;
  230. if (ncvarget1(cdfid, va_id[iv], where, (void *) &val) != -1) {
  231. if (val != fillval) {
  232. error("%s: unwritten byte not FILL_BYTE", pname);
  233. nerrs++;
  234. }
  235. } else {
  236. error("%s: ncvarget1 failure for byte", pname);
  237. nerrs++;
  238. }
  239. }
  240. break;
  241. case NC_CHAR:
  242. {
  243. char val, fillval = FILL_CHAR;
  244. if (ncvarget1(cdfid, va_id[iv], where, (void *) &val) != -1) {
  245. if (val != fillval) {
  246. error("%s: unwritten char not FILL_CHAR", pname);
  247. nerrs++;
  248. }
  249. } else {
  250. error("%s: ncvarget1 failure for char", pname);
  251. nerrs++;
  252. }
  253. }
  254. break;
  255. case NC_SHORT:
  256. {
  257. short val, fillval = FILL_SHORT;
  258. if (ncvarget1(cdfid, va_id[iv], where, (void *) &val) != -1) {
  259. if (val != fillval) {
  260. error("%s: unwritten short not FILL_SHORT", pname);
  261. nerrs++;
  262. }
  263. } else {
  264. error("%s: ncvarget1 failure for short", pname);
  265. nerrs++;
  266. }
  267. }
  268. break;
  269. case NC_LONG:
  270. {
  271. nclong val, fillval = FILL_LONG;
  272. if (ncvarget1(cdfid, va_id[iv], where, (void *) &val) != -1) {
  273. if (val != fillval) {
  274. error("%s: unwritten long not FILL_LONG", pname);
  275. nerrs++;
  276. }
  277. } else {
  278. error("%s: ncvarget1 failure for long", pname);
  279. nerrs++;
  280. }
  281. }
  282. break;
  283. #define absval(x) ( (x) < 0 ? -(x) : (x) )
  284. case NC_FLOAT:
  285. {
  286. float val, fillval = FILL_FLOAT;
  287. if (ncvarget1(cdfid, va_id[iv], where, (void *) &val) != -1) {
  288. if (absval(val-fillval) > absval(float_eps * fillval)) {
  289. error("%s: unwritten float not FILL_FLOAT", pname);
  290. nerrs++;
  291. }
  292. } else {
  293. error("%s: ncvarget1 failure for float", pname);
  294. nerrs++;
  295. }
  296. }
  297. break;
  298. case NC_DOUBLE:
  299. {
  300. double val, fillval = FILL_DOUBLE;
  301. if (ncvarget1(cdfid, va_id[iv], where, (void *) &val) != -1) {
  302. #define DBL_FUDGE 8.0 /* can be 1.0 on every platform we've seen
  303. except for VAX/Ultrix 4.3 with cc */
  304. if (absval(val-fillval) > DBL_FUDGE * absval(double_eps * fillval)) {
  305. error("%s: unwritten double not FILL_DOUBLE", pname);
  306. nerrs++;
  307. }
  308. } else {
  309. error("%s: ncvarget1 failure for double", pname);
  310. nerrs++;
  311. }
  312. }
  313. break;
  314. }
  315. }
  316. if (ncclose (cdfid) == -1) {
  317. error("%s: ncclose failed", pname);
  318. return ++nerrs;
  319. }
  320. free (tmp.dims);
  321. free (tmp.name);
  322. for (iv = 0; iv < nv; iv++)
  323. if (va[iv].dims)
  324. free(va[iv].dims);
  325. if (nerrs > 0)
  326. (void) fprintf(stderr,"FAILED! ***\n");
  327. else
  328. (void) fprintf(stderr,"ok ***\n");
  329. return nerrs;
  330. }