00001
00002
00003
00004
00005
00006
00007 #include <stdio.h>
00008 #include <ctype.h>
00009 #include <stdlib.h>
00010 #include <string.h>
00011 #ifndef NO_FLOAT_H
00012 #include <float.h>
00013 #endif
00014
00015 #include <netcdf.h>
00016 #include "ncdump.h"
00017 #include "dumplib.h"
00018 #include "vardata.h"
00019
00020 static float float_epsilon(void);
00021 static double double_epsilon(void);
00022 static void init_epsilons(void);
00023 static void printbval(char* sout, const char* fmt, const struct ncvar* varp,
00024 signed char val);
00025 static void printsval(char* sout, const char* fmt, const struct ncvar* varp,
00026 short val);
00027 static void printival(char* sout, const char* fmt, const struct ncvar* varp,
00028 int val);
00029 static void printfval(char* sout, const char* fmt, const struct ncvar* varp,
00030 float val);
00031 static void printdval(char* sout, const char* fmt, const struct ncvar* varp,
00032 double val);
00033 static void lastdelim(boolean more, boolean lastrow);
00034 static void annotate(const struct ncvar* vp, const struct fspec* fsp,
00035 const size_t* cor, long iel);
00036 static void pr_tvals(const struct ncvar *vp, size_t len, const char *fmt,
00037 boolean more, boolean lastrow, const char *vals,
00038 const struct fspec* fsp, const size_t *cor);
00039 static void pr_bvals(const struct ncvar *vp, size_t len, const char *fmt,
00040 boolean more, boolean lastrow, const signed char *vals,
00041 const struct fspec* fsp, const size_t *cor);
00042 static void pr_svals(const struct ncvar *vp, size_t len, const char *fmt,
00043 boolean more, boolean lastrow, const short *vals,
00044 const struct fspec* fsp, const size_t *cor);
00045 static void pr_ivals(const struct ncvar *vp, size_t len, const char *fmt,
00046 boolean more, boolean lastrow, const int *vals,
00047 const struct fspec* fsp, const size_t *cor);
00048 static void pr_fvals(const struct ncvar *vp, size_t len, const char *fmt,
00049 boolean more, boolean lastrow, const float *vals,
00050 const struct fspec* fsp, const size_t *cor);
00051 static void pr_dvals(const struct ncvar *vp, size_t len, const char *fmt,
00052 boolean more, boolean lastrow, const double *vals,
00053 const struct fspec* fsp, const size_t *cor);
00054 static int upcorner(const size_t* dims, int ndims, size_t* odom,
00055 const size_t* add);
00056 static void lastdelim2 (boolean more, boolean lastrow);
00057
00058 #define STREQ(a, b) (*(a) == *(b) && strcmp((a), (b)) == 0)
00059
00060 static float float_eps;
00061 static double double_eps;
00062
00063 static float
00064 float_epsilon(void)
00065 {
00066 float float_eps;
00067 #ifndef NO_FLOAT_H
00068 float_eps = FLT_EPSILON;
00069 #else
00070 {
00071 float etop, ebot, eps;
00072 float one = 1.0;
00073 float two = 2.0;
00074 etop = 1.0;
00075 ebot = 0.0;
00076 eps = ebot + (etop - ebot)/two;
00077 while (eps != ebot && eps != etop) {
00078 float epsp1;
00079
00080 epsp1 = one + eps;
00081 if (epsp1 > one)
00082 etop = eps;
00083 else
00084 ebot = eps;
00085 eps = ebot + (etop - ebot)/two;
00086 }
00087 float_eps = two * etop;
00088 }
00089 #endif
00090 return float_eps;
00091 }
00092
00093
00094 static double
00095 double_epsilon(void)
00096 {
00097 double double_eps;
00098 #ifndef NO_FLOAT_H
00099 double_eps = DBL_EPSILON;
00100 #else
00101 {
00102 double etop, ebot, eps;
00103 double one = 1.0;
00104 double two = 2.0;
00105 etop = 1.0;
00106 ebot = 0.0;
00107 eps = ebot + (etop - ebot)/two;
00108 while (eps != ebot && eps != etop) {
00109 double epsp1;
00110
00111 epsp1 = one + eps;
00112 if (epsp1 > one)
00113 etop = eps;
00114 else
00115 ebot = eps;
00116 eps = ebot + (etop - ebot)/two;
00117 }
00118 double_eps = two * etop;
00119 }
00120 #endif
00121 return double_eps;
00122 }
00123
00124
00125 static void
00126 init_epsilons(void)
00127 {
00128 float_eps = float_epsilon();
00129 double_eps = double_epsilon();
00130 }
00131
00132
00133
00134
00135
00136
00137 static void
00138 printbval(
00139 char *sout,
00140 const char *fmt,
00141 const struct ncvar *varp,
00142 signed char val
00143 )
00144 {
00145 if (varp->has_fillval) {
00146 double fillval = varp->fillval;
00147 if(fillval == val) {
00148 (void) sprintf(sout, FILL_STRING);
00149 return;
00150 }
00151 }
00152 (void) sprintf(sout, fmt, val);
00153 }
00154
00155
00156
00157
00158
00159
00160 static void
00161 printsval(
00162 char *sout,
00163 const char *fmt,
00164 const struct ncvar *varp,
00165 short val
00166 )
00167 {
00168 if (varp->has_fillval) {
00169 double fillval = varp->fillval;
00170 if(fillval == val) {
00171 (void) sprintf(sout, FILL_STRING);
00172 return;
00173 }
00174 }
00175 (void) sprintf(sout, fmt, val);
00176 }
00177
00178
00179
00180
00181
00182
00183
00184 static void
00185 printival(
00186 char *sout,
00187 const char *fmt,
00188 const struct ncvar *varp,
00189 int val
00190 )
00191 {
00192 if (varp->has_fillval) {
00193 int fillval = (int)varp->fillval;
00194 if(fillval == val) {
00195 (void) sprintf(sout, FILL_STRING);
00196 return;
00197 }
00198 }
00199 (void) sprintf(sout, fmt, val);
00200 }
00201
00202
00203 #define absval(x) ( (x) < 0 ? -(x) : (x) )
00204
00205
00206
00207
00208
00209
00210
00211 static void
00212 printfval(
00213 char *sout,
00214 const char *fmt,
00215 const struct ncvar *varp,
00216 float val
00217 )
00218 {
00219 if(varp->has_fillval) {
00220 double fillval = varp->fillval;
00221 if((val > 0) == (fillval > 0) &&
00222 (absval(val - fillval) <= absval(float_eps * fillval))) {
00223 (void) sprintf(sout, FILL_STRING);
00224 return;
00225 }
00226 }
00227 (void) sprintf(sout, fmt, val);
00228 }
00229
00230
00231
00232
00233
00234
00235
00236
00237 static void
00238 printdval(
00239 char *sout,
00240 const char *fmt,
00241 const struct ncvar *varp,
00242 double val
00243 )
00244 {
00245 if(varp->has_fillval) {
00246 double fillval = varp->fillval;
00247 if((val > 0) == (fillval > 0) &&
00248 (absval(val - fillval) <= absval(double_eps * fillval))) {
00249 (void) sprintf(sout, FILL_STRING);
00250 return;
00251 }
00252 }
00253 (void) sprintf(sout, fmt, val);
00254 }
00255
00256
00257
00258
00259
00260 static void
00261 lastdelim (boolean more, boolean lastrow)
00262 {
00263 if (more) {
00264 Printf(", ");
00265 } else {
00266 if(lastrow) {
00267 Printf(";");
00268 } else {
00269 Printf(",");
00270 }
00271 }
00272 }
00273
00274
00275
00276
00277 static void
00278 lastdelim2 (boolean more, boolean lastrow)
00279 {
00280 if (more) {
00281 lput(", ");
00282 } else {
00283 if(lastrow) {
00284 lput(" ;");
00285 lput("\n");
00286 } else {
00287 lput(",\n");
00288 lput(" ");
00289 }
00290 }
00291 }
00292
00293
00294
00295
00296
00297 static void
00298 annotate(
00299 const struct ncvar *vp,
00300 const struct fspec* fsp,
00301 const size_t *cor,
00302 long iel
00303 )
00304 {
00305 int vrank = vp->ndims;
00306 int id;
00307
00308
00309 (void) printf(" // %s(", vp->name);
00310 switch (fsp->data_lang) {
00311 case LANG_C:
00312
00313 for (id = 0; id < vrank-1; id++)
00314 Printf("%lu,", (unsigned long) cor[id]);
00315 Printf("%lu", (unsigned long) cor[id] + iel);
00316 break;
00317 case LANG_F:
00318
00319 Printf("%lu", (unsigned long) cor[vrank-1] + iel + 1);
00320 for (id = vrank-2; id >=0 ; id--) {
00321 Printf(",%lu", 1 + (unsigned long) cor[id]);
00322 }
00323 break;
00324 }
00325 Printf(")\n ");
00326 }
00327
00328
00329
00330
00331
00332
00333 static void
00334 pr_tvals(
00335 const struct ncvar *vp,
00336 size_t len,
00337 const char *fmt,
00338
00339
00340
00341 boolean more,
00342
00343 boolean lastrow,
00344
00345
00346 const char *vals,
00347 const struct fspec* fsp,
00348 const size_t *cor
00349 )
00350 {
00351 long iel;
00352 const char *sp;
00353 unsigned char uc;
00354 char sout[100];
00355
00356 if (fmt == 0 || STREQ(fmt,"%s") || STREQ(fmt,"")) {
00357 Printf("\"");
00358
00359 sp = vals + len;
00360 while (len != 0 && *--sp == '\0')
00361 len--;
00362 for (iel = 0; iel < len; iel++)
00363 switch (uc = *vals++ & 0377) {
00364 case '\b':
00365 Printf("\\b");
00366 break;
00367 case '\f':
00368 Printf("\\f");
00369 break;
00370 case '\n':
00371 Printf("\\n\",\n \"");
00372 break;
00373 case '\r':
00374 Printf("\\r");
00375 break;
00376 case '\t':
00377 Printf("\\t");
00378 break;
00379 case '\v':
00380 Printf("\\v");
00381 break;
00382 case '\\':
00383 Printf("\\\\");
00384 break;
00385 case '\'':
00386 Printf("\\\'");
00387 break;
00388 case '\"':
00389 Printf("\\\"");
00390 break;
00391 default:
00392 if (isprint(uc))
00393 Printf("%c",uc);
00394 else
00395 Printf("\\%.3o",uc);
00396 break;
00397 }
00398 Printf("\"");
00399 if (fsp->full_data_cmnts) {
00400 Printf("\"");
00401 lastdelim (more, lastrow);
00402 annotate (vp, fsp, (size_t *)cor, 0L);
00403 }
00404 } else {
00405 for (iel = 0; iel < len-1; iel++) {
00406 if (fsp->full_data_cmnts) {
00407 Printf(fmt, *vals++);
00408 Printf(", ");
00409 annotate (vp, fsp, (size_t *)cor, iel);
00410 } else {
00411 (void) sprintf(sout, fmt, *vals++);
00412 (void) strcat(sout, ", ");
00413 lput(sout);
00414 }
00415 }
00416 if (fsp->full_data_cmnts) {
00417 Printf(fmt, *vals++);
00418 lastdelim (more, lastrow);
00419 annotate (vp, fsp, (size_t *)cor, iel);
00420 } else {
00421 (void) sprintf(sout, fmt, *vals++);
00422 lput(sout);
00423 }
00424 }
00425 if (!fsp->full_data_cmnts) {
00426 lastdelim2 (more, lastrow);
00427 }
00428 }
00429
00430
00431
00432
00433
00434
00435 static void
00436 pr_bvals(
00437 const struct ncvar *vp,
00438 size_t len,
00439 const char *fmt,
00440
00441
00442
00443 boolean more,
00444
00445 boolean lastrow,
00446
00447
00448 const signed char *vals,
00449 const struct fspec* fsp,
00450 const size_t *cor
00451 )
00452 {
00453 long iel;
00454 char sout[100];
00455
00456 for (iel = 0; iel < len-1; iel++) {
00457 printbval(sout, fmt, vp, *vals++);
00458 if (fsp->full_data_cmnts) {
00459 Printf(sout);
00460 Printf(",");
00461 annotate (vp, fsp, cor, iel);
00462 } else {
00463 (void) strcat(sout, ", ");
00464 lput(sout);
00465 }
00466 }
00467 printbval(sout, fmt, vp, *vals++);
00468 if (fsp->full_data_cmnts) {
00469 Printf(sout);
00470 lastdelim (more, lastrow);
00471 annotate (vp, fsp, cor, iel);
00472 } else {
00473 lput(sout);
00474 lastdelim2 (more, lastrow);
00475 }
00476 }
00477
00478
00479
00480
00481
00482
00483 static void
00484 pr_svals(
00485 const struct ncvar *vp,
00486 size_t len,
00487 const char *fmt,
00488
00489
00490
00491 boolean more,
00492
00493 boolean lastrow,
00494
00495
00496 const short *vals,
00497 const struct fspec* fsp,
00498 const size_t *cor
00499 )
00500 {
00501 long iel;
00502 char sout[100];
00503
00504 for (iel = 0; iel < len-1; iel++) {
00505 printsval(sout, fmt, vp, *vals++);
00506 if (fsp->full_data_cmnts) {
00507 Printf(sout);
00508 Printf(",");
00509 annotate (vp, fsp, cor, iel);
00510 } else {
00511 (void) strcat(sout, ", ");
00512 lput(sout);
00513 }
00514 }
00515 printsval(sout, fmt, vp, *vals++);
00516 if (fsp->full_data_cmnts) {
00517 Printf(sout);
00518 lastdelim (more, lastrow);
00519 annotate (vp, fsp, cor, iel);
00520 } else {
00521 lput(sout);
00522 lastdelim2 (more, lastrow);
00523 }
00524 }
00525
00526
00527
00528
00529
00530
00531
00532
00533 static void
00534 pr_ivals(
00535 const struct ncvar *vp,
00536 size_t len,
00537 const char *fmt,
00538
00539
00540
00541 boolean more,
00542
00543 boolean lastrow,
00544
00545
00546 const int *vals,
00547 const struct fspec* fsp,
00548 const size_t *cor
00549 )
00550 {
00551 long iel;
00552 char sout[100];
00553
00554 for (iel = 0; iel < len-1; iel++) {
00555 printival(sout, fmt, vp, *vals++);
00556 if (fsp->full_data_cmnts) {
00557 Printf(sout);
00558 Printf(",");
00559 annotate (vp, fsp, cor, iel);
00560 } else {
00561 (void) strcat(sout, ", ");
00562 lput(sout);
00563 }
00564 }
00565 printival(sout, fmt, vp, *vals++);
00566 if (fsp->full_data_cmnts) {
00567 Printf(sout);
00568 lastdelim (more, lastrow);
00569 annotate (vp, fsp, cor, iel);
00570 } else {
00571 lput(sout);
00572 lastdelim2 (more, lastrow);
00573 }
00574 }
00575
00576
00577
00578
00579
00580
00581 static void
00582 pr_fvals(
00583 const struct ncvar *vp,
00584 size_t len,
00585 const char *fmt,
00586
00587
00588
00589 boolean more,
00590
00591 boolean lastrow,
00592
00593
00594 const float *vals,
00595 const struct fspec* fsp,
00596 const size_t *cor
00597 )
00598 {
00599 long iel;
00600 char sout[100];
00601
00602 for (iel = 0; iel < len-1; iel++) {
00603 printfval(sout, fmt, vp, *vals++);
00604 if (fsp->full_data_cmnts) {
00605 Printf(sout);
00606 Printf(",");
00607 annotate (vp, fsp, cor, iel);
00608 } else {
00609 (void) strcat(sout, ", ");
00610 lput(sout);
00611 }
00612 }
00613 printfval(sout, fmt, vp, *vals++);
00614 if (fsp->full_data_cmnts) {
00615 Printf(sout);
00616 lastdelim (more, lastrow);
00617 annotate (vp, fsp, cor, iel);
00618 } else {
00619 lput(sout);
00620 lastdelim2 (more, lastrow);
00621 }
00622 }
00623
00624
00625
00626
00627
00628
00629 static void
00630 pr_dvals(
00631 const struct ncvar *vp,
00632 size_t len,
00633 const char *fmt,
00634
00635
00636
00637 boolean more,
00638
00639 boolean lastrow,
00640
00641
00642 const double *vals,
00643 const struct fspec* fsp,
00644 const size_t *cor
00645 )
00646 {
00647 long iel;
00648 char sout[100];
00649
00650 for (iel = 0; iel < len-1; iel++) {
00651 printdval(sout, fmt, vp, *vals++);
00652 if (fsp->full_data_cmnts) {
00653 Printf(sout);
00654 Printf(",");
00655 annotate (vp, fsp, cor, iel);
00656 } else {
00657 (void) strcat(sout, ", ");
00658 lput(sout);
00659 }
00660 }
00661 printdval(sout, fmt, vp, *vals++);
00662 if (fsp->full_data_cmnts) {
00663 Printf(sout);
00664 lastdelim (more, lastrow);
00665 annotate (vp, fsp, cor, iel);
00666 } else {
00667 lput(sout);
00668 lastdelim2 (more, lastrow);
00669 }
00670 }
00671
00672
00673
00674
00675
00676
00677 static int
00678 upcorner(
00679 const size_t *dims,
00680 int ndims,
00681 size_t* odom,
00682 const size_t* add
00683 )
00684 {
00685 int id;
00686 int ret = 1;
00687
00688 for (id = ndims-1; id > 0; id--) {
00689 odom[id] += add[id];
00690 if(odom[id] >= dims[id]) {
00691 odom[id-1]++;
00692 odom[id] -= dims[id];
00693 }
00694 }
00695 odom[0] += add[0];
00696 if (odom[0] >= dims[0])
00697 ret = 0;
00698 return ret;
00699 }
00700
00701
00702
00703 int
00704 vardata(
00705 const struct ncvar *vp,
00706 size_t vdims[],
00707 int ncid,
00708 int varid,
00709 const struct fspec* fsp
00710 )
00711 {
00712 size_t cor[NC_MAX_DIMS];
00713 size_t edg[NC_MAX_DIMS];
00714 size_t add[NC_MAX_DIMS];
00715 #define VALBUFSIZ 1000
00716 double vals[VALBUFSIZ] ;
00717
00718 int gulp = VALBUFSIZ;
00719
00720 int id;
00721 int ir;
00722 size_t nels;
00723 size_t ncols;
00724 size_t nrows;
00725 int vrank = vp->ndims;
00726 static int initeps = 0;
00727
00728
00729 char *fmt = get_fmt(ncid, varid, vp->type);
00730
00731 if (!initeps) {
00732 init_epsilons();
00733 initeps = 1;
00734 }
00735
00736 nels = 1;
00737 for (id = 0; id < vrank; id++) {
00738 cor[id] = 0;
00739 edg[id] = 1;
00740 nels *= vdims[id];
00741 }
00742
00743 if (vrank <= 1) {
00744 Printf("\n %s = ", vp->name);
00745 set_indent ((int)strlen(vp->name) + 4);
00746 } else {
00747 Printf("\n %s =\n ", vp->name);
00748 set_indent (2);
00749 }
00750
00751 if (vrank < 1) {
00752 ncols = 1;
00753 } else {
00754 ncols = vdims[vrank-1];
00755 edg[vrank-1] = vdims[vrank-1];
00756 for (id = 0; id < vrank; id++)
00757 add[id] = 0;
00758 if (vrank > 1)
00759 add[vrank-2] = 1;
00760 }
00761 nrows = nels/ncols;
00762
00763 for (ir = 0; ir < nrows; ir++) {
00764
00765
00766
00767
00768
00769 size_t corsav;
00770 int left = (int)ncols;
00771 boolean lastrow;
00772
00773 if (vrank > 0) {
00774 corsav = cor[vrank-1];
00775 if (fsp->brief_data_cmnts != false
00776 && vrank > 1
00777 && left > 0) {
00778 Printf("// %s(",vp->name);
00779 switch (fsp->data_lang) {
00780 case LANG_C:
00781
00782 for (id = 0; id < vrank-1; id++)
00783 Printf("%lu,", (unsigned long)cor[id]);
00784 if (vdims[vrank-1] == 1)
00785 Printf("0");
00786 else
00787 Printf(" 0-%lu", (unsigned long)vdims[vrank-1]-1);
00788 break;
00789 case LANG_F:
00790
00791 if (vdims[vrank-1] == 1)
00792 Printf("1");
00793 else
00794 Printf("1-%lu ", (unsigned long)vdims[vrank-1]);
00795 for (id = vrank-2; id >=0 ; id--) {
00796 Printf(",%lu", (unsigned long)(1 + cor[id]));
00797 }
00798 break;
00799 }
00800 Printf(")\n ");
00801 set_indent(4);
00802 }
00803 }
00804 lastrow = (boolean)(ir == nrows-1);
00805 while (left > 0) {
00806 size_t toget = left < gulp ? left : gulp;
00807 if (vrank > 0)
00808 edg[vrank-1] = toget;
00809 switch(vp->type) {
00810 case NC_CHAR:
00811 NC_CHECK(
00812 nc_get_vara_text(ncid, varid, cor, edg, (char *)vals) );
00813 pr_tvals(vp, toget, fmt, left > toget, lastrow,
00814 (char *) vals, fsp, cor);
00815 break;
00816 case NC_BYTE:
00817 NC_CHECK(
00818 nc_get_vara_schar(ncid, varid, cor, edg, (signed char *)vals) );
00819 pr_bvals(vp, toget, fmt, left > toget, lastrow,
00820 (signed char *) vals, fsp, cor);
00821 break;
00822 case NC_SHORT:
00823 NC_CHECK(
00824 nc_get_vara_short(ncid, varid, cor, edg, (short *)vals) );
00825 pr_svals(vp, toget, fmt, left > toget, lastrow,
00826 (short *) vals, fsp, cor);
00827 break;
00828 case NC_INT:
00829 NC_CHECK(
00830 nc_get_vara_int(ncid, varid, cor, edg, (int *)vals) );
00831 pr_ivals(vp, toget, fmt, left > toget, lastrow,
00832 (int *) vals, fsp, cor);
00833 break;
00834 case NC_FLOAT:
00835 NC_CHECK(
00836 nc_get_vara_float(ncid, varid, cor, edg, (float *)vals) );
00837 pr_fvals(vp, toget, fmt, left > toget, lastrow,
00838 (float *) vals, fsp, cor);
00839 break;
00840 case NC_DOUBLE:
00841 NC_CHECK(
00842 nc_get_vara_double(ncid, varid, cor, edg, (double *)vals) );
00843 pr_dvals(vp, toget, fmt, left > toget, lastrow,
00844 (double *) vals, fsp, cor);
00845 break;
00846 default:
00847 error("vardata: bad type");
00848 }
00849 left -= toget;
00850 if (vrank > 0)
00851 cor[vrank-1] += toget;
00852 }
00853 if (vrank > 0)
00854 cor[vrank-1] = corsav;
00855 if (ir < nrows-1)
00856 if (!upcorner(vdims,vp->ndims,cor,add))
00857 error("vardata: odometer overflowed!");
00858 set_indent(2);
00859 }
00860
00861 return 0;
00862 }