Annotation of OpenXM_contrib/gnuplot/binary.c, Revision 1.1
1.1 ! maekawa 1: #ifndef lint
! 2: static char *RCSid = "$Id: binary.c,v 1.10 1998/04/14 00:14:49 drd Exp $";
! 3: #endif
! 4:
! 5: /*
! 6: * The addition of gnubin and binary, along with a small patch
! 7: * to command.c, will permit gnuplot to plot binary files.
! 8: * gnubin - contains the code that relies on gnuplot include files
! 9: * and other definitions
! 10: * binary - contains those things that are independent of those
! 11: * definitions and files
! 12: *
! 13: * With these routines, hidden line removal of your binary data is possible!
! 14: *
! 15: * Last update: 3/29/92 memory allocation bugs fixed. jvdwoude@hut.nl
! 16: * 3/09/92 spelling errors, general cleanup, use alloc with no
! 17: * nasty fatal errors
! 18: * 3/03/92 for Gnuplot 3.24.
! 19: * Created from code for written by RKC for gnuplot 2.0b.
! 20: *
! 21: * Copyright (c) 1991,1992 Robert K. Cunningham, MIT Lincoln Laboratory
! 22: *
! 23: */
! 24:
! 25: #include "plot.h" /* We have to get TRUE and FALSE */
! 26: #include "stdfn.h"
! 27: #include "binary.h"
! 28:
! 29: /*
! 30: * This routine scans the first block of the file to see if the file is a
! 31: * binary file. A file is considered binary if 10% of the characters in it
! 32: * are not in the ascii character set. (values < 128), or if a NUL is found.
! 33: * I hope this doesn't break when used on the bizzare PC's.
! 34: */
! 35: int is_binary_file(fp)
! 36: register FILE *fp;
! 37: {
! 38: register int i, len;
! 39: register int odd; /* Contains a count of the odd characters */
! 40: long where;
! 41: register unsigned char *c;
! 42: unsigned char buffer[512];
! 43:
! 44: if ((where = ftell(fp)) == -1) { /* Find out where we start */
! 45: fprintf(stderr, "Notice: Assuming unseekable data is not binary\n");
! 46: return (FALSE);
! 47: } else {
! 48: rewind(fp);
! 49:
! 50: len = fread(buffer, sizeof(char), 512, fp);
! 51: if (len <= 0) /* Empty file is declared ascii */
! 52: return (FALSE);
! 53:
! 54: c = buffer;
! 55:
! 56: /* now scan buffer to look for odd characters */
! 57: odd = 0;
! 58: for (i = 0; i < len; i++, c++) {
! 59: if (!*c) { /* NUL _never_ allowed in text */
! 60: odd += len;
! 61: break;
! 62: } else if ((*c & 128) || /* Meta-characters--we hope it's not formatting */
! 63: (*c == 127) || /* DEL */
! 64: (*c < 32 &&
! 65: *c != '\n' && *c != '\r' && *c != '\b' &&
! 66: *c != '\t' && *c != '\f' && *c != 27 /*ESC */ ))
! 67: odd++;
! 68: }
! 69:
! 70: fseek(fp, where, 0); /* Go back to where we started */
! 71:
! 72: if (odd * 10 > len) /* allow 10% of the characters to be odd */
! 73: return (TRUE);
! 74: else
! 75: return (FALSE);
! 76: }
! 77: }
! 78:
! 79:
! 80: /*========================= I/O Routines ================================
! 81: These may be useful for situations other than just gnuplot. Note that I
! 82: have included the reading _and_ the writing routines, so others can create
! 83: the file as well as read the file.
! 84: */
! 85:
! 86: /*
! 87: This function reads a matrix from a stream
! 88:
! 89: This routine never returns anything other than vectors and arrays
! 90: that range from 0 to some number.
! 91:
! 92: */
! 93: #define START_ROWS 100 /* Each of these must be at least 1 */
! 94: #define ADD_ROWS 50
! 95: int fread_matrix(fin, ret_matrix, nr, nc, row_title, column_title)
! 96: FILE *fin;
! 97: float GPFAR *GPFAR * GPFAR * ret_matrix, GPFAR * GPFAR * row_title,
! 98: GPFAR * GPFAR * column_title;
! 99: int *nr, *nc;
! 100: {
! 101: float GPFAR *GPFAR * m, GPFAR * rt, GPFAR * ct;
! 102: register int num_rows = START_ROWS;
! 103: register int num_cols;
! 104: register int current_row = 0;
! 105: register float GPFAR *GPFAR * temp_array;
! 106: float fdummy;
! 107:
! 108: if (fread(&fdummy, sizeof(fdummy), 1, fin) != 1)
! 109: return FALSE;
! 110:
! 111: num_cols = (int) fdummy;
! 112:
! 113: /*
! 114: Choose a reasonable number of rows,
! 115: allocate space for it and continue until this space
! 116: runs out, then extend the matrix as necessary.
! 117: */
! 118: ct = vector(0, num_cols - 1);
! 119: fread(ct, sizeof(*ct), num_cols, fin);
! 120:
! 121: rt = vector(0, num_rows - 1);
! 122: m = matrix(0, num_rows - 1, 0, num_cols - 1);
! 123:
! 124: while (fread(&rt[current_row], sizeof(rt[current_row]), 1, fin) == 1) {
! 125: /* We've got another row */
! 126: if (fread(m[current_row], sizeof(*(m[current_row])), num_cols, fin) != num_cols)
! 127: return (FALSE); /* Not a True matrix */
! 128:
! 129: current_row++;
! 130: if (current_row >= num_rows) { /* We've got to make a bigger rowsize */
! 131: temp_array = extend_matrix(m, 0, num_rows - 1, 0, num_cols - 1,
! 132: num_rows + ADD_ROWS - 1, num_cols - 1);
! 133: rt = extend_vector(rt, 0, num_rows - 1, num_rows + ADD_ROWS - 1);
! 134:
! 135: num_rows += ADD_ROWS;
! 136: m = temp_array;
! 137: }
! 138: }
! 139: /* finally we force the matrix to be the correct row size */
! 140: /* bug fixed. procedure called with incorrect 6th argument.
! 141: * jvdwoude@hut.nl */
! 142: temp_array = retract_matrix(m, 0, num_rows - 1, 0, num_cols - 1, current_row - 1, num_cols - 1);
! 143: /* Now save the things that change */
! 144: *ret_matrix = temp_array;
! 145: *row_title = retract_vector(rt, 0, num_rows - 1, current_row - 1);
! 146: *column_title = ct;
! 147: *nr = current_row; /* Really the total number of rows */
! 148: *nc = num_cols;
! 149: return (TRUE);
! 150: }
! 151:
! 152: /* This writes a matrix to a stream
! 153: Note that our ranges are inclusive ranges--and we can specify subsets.
! 154: This behaves similarly to the xrange and yrange operators in gnuplot
! 155: that we all are familiar with.
! 156: */
! 157: int fwrite_matrix(fout, m, nrl, nrh, ncl, nch, row_title, column_title)
! 158: register FILE *fout;
! 159: register float GPFAR *GPFAR * m, GPFAR * row_title, GPFAR * column_title;
! 160: register int nrl, nrh, ncl, nch;
! 161: {
! 162: register int j;
! 163: float length;
! 164: register int col_length;
! 165: register int status;
! 166: float GPFAR *title = NULL;
! 167:
! 168: length = (float) (col_length = nch - ncl + 1);
! 169:
! 170: if ((status = fwrite((char *) &length, sizeof(float), 1, fout)) != 1) {
! 171: fprintf(stderr, "fwrite 1 returned %d\n", status);
! 172: return (FALSE);
! 173: }
! 174: if (!column_title) {
! 175: column_title = title = vector(ncl, nch);
! 176: for (j = ncl; j <= nch; j++)
! 177: title[j] = (float) j;
! 178: }
! 179: fwrite((char *) column_title, sizeof(float), col_length, fout);
! 180: if (title) {
! 181: free_vector(title, ncl, nch);
! 182: title = NULL;
! 183: }
! 184: if (!row_title) {
! 185: row_title = title = vector(nrl, nrh);
! 186: for (j = nrl; j <= nrh; j++)
! 187: title[j] = (float) j;
! 188: }
! 189: for (j = nrl; j <= nrh; j++) {
! 190: fwrite((char *) &row_title[j], sizeof(float), 1, fout);
! 191: fwrite((char *) (m[j] + ncl), sizeof(float), col_length, fout);
! 192: }
! 193: if (title)
! 194: free_vector(title, nrl, nrh);
! 195:
! 196: return (TRUE);
! 197: }
! 198:
! 199: /*===================== Support routines ==============================*/
! 200:
! 201: /******************************** VECTOR *******************************
! 202: * The following routines interact with vectors.
! 203: *
! 204: * If there is an error we don't really return - int_error breaks us out.
! 205: *
! 206: * This subroutine based on a subroutine listed in "Numerical Recipies in C",
! 207: * by Press, Flannery, Teukoilsky and Vetterling (1988).
! 208: *
! 209: */
! 210: float GPFAR *vector(nl, nh)
! 211: register int nl, nh;
! 212: {
! 213: register float GPFAR *vec;
! 214:
! 215: if (!(vec = (float GPFAR *) gp_alloc((unsigned long) (nh - nl + 1) * sizeof(float), NULL))) {
! 216: int_error("not enough memory to create vector", NO_CARET);
! 217: return NULL; /* Not reached */
! 218: }
! 219: return (vec - nl);
! 220: }
! 221:
! 222:
! 223: /*
! 224: * Free a vector allocated above
! 225: *
! 226: * This subroutine based on a subroutine listed in "Numerical Recipies in C",
! 227: * by Press, Flannery, Teukoilsky and Vetterling (1988).
! 228: *
! 229: */
! 230: void free_vector(vec, nl, nh)
! 231: float GPFAR *vec;
! 232: int nl, nh;
! 233: {
! 234: free(vec + nl);
! 235: }
! 236:
! 237: /************ Routines to modify the length of a vector ****************/
! 238: float GPFAR *
! 239: extend_vector(vec, old_nl, old_nh, new_nh)
! 240: float GPFAR *vec;
! 241: register int old_nl, old_nh, new_nh;
! 242: {
! 243: register float GPFAR *new_v;
! 244: new_v = (float GPFAR *) gp_realloc((void *) (vec + old_nl),
! 245: (unsigned long) (new_nh - old_nl + 1) * sizeof(float),
! 246: "extend vector");
! 247: return new_v - old_nl;
! 248: }
! 249:
! 250: float GPFAR *
! 251: retract_vector(v, old_nl, old_nh, new_nh)
! 252: float GPFAR *v;
! 253: register int old_nl, old_nh, new_nh;
! 254: {
! 255: register float GPFAR *new_v;
! 256: new_v = (float GPFAR *) gp_realloc((void *) (v + old_nl),
! 257: (unsigned long) (new_nh - old_nl + 1) * sizeof(float), "retract vector");
! 258: return new_v - old_nl;
! 259: }
! 260:
! 261:
! 262: /***************************** MATRIX ************************
! 263: *
! 264: * The following routines work with matricies
! 265: *
! 266: * I always get confused with this, so here I write it down:
! 267: * for nrl<= nri <=nrh and
! 268: * for ncl<= ncj <=nch
! 269: *
! 270: * This matrix is accessed as:
! 271: *
! 272: * matrix[nri][ncj];
! 273: * where nri is the offset to the pointer to a vector where the
! 274: * ncjth element lies.
! 275: *
! 276: * If there is an error we don't really return - int_error breaks us out.
! 277: *
! 278: * This subroutine based on a subroutine listed in "Numerical Recipies in C",
! 279: * by Press, Flannery, Teukoilsky and Vetterling (1988).
! 280: *
! 281: */
! 282: float
! 283: GPFAR *GPFAR * matrix(nrl, nrh, ncl, nch)
! 284: register int nrl, nrh, ncl, nch;
! 285: {
! 286: register int i;
! 287: register float GPFAR *GPFAR * m;
! 288:
! 289: m = (float GPFAR * GPFAR *) gp_alloc((unsigned long) (nrh - nrl + 1) * sizeof(float GPFAR *), "matrix");
! 290: m -= nrl;
! 291:
! 292: for (i = nrl; i <= nrh; i++) {
! 293: if (!(m[i] = (float GPFAR *) gp_alloc((unsigned long) (nch - ncl + 1) * sizeof(float), NULL))) {
! 294: free_matrix(m, nrl, i - 1, ncl, nch);
! 295: int_error("not enough memory to create matrix", NO_CARET);
! 296: return NULL;
! 297: }
! 298: m[i] -= ncl;
! 299: }
! 300: return m;
! 301: }
! 302: /*
! 303: * Free a matrix allocated above
! 304: *
! 305: *
! 306: * This subroutine based on a subroutine listed in "Numerical Recipies in C",
! 307: * by Press, Flannery, Teukoilsky and Vetterling (1988).
! 308: *
! 309: */
! 310: void free_matrix(m, nrl, nrh, ncl, nch)
! 311: float GPFAR *GPFAR * m;
! 312: unsigned nrl, nrh, ncl, nch;
! 313: {
! 314: register unsigned int i;
! 315:
! 316: for (i = nrl; i <= nrh; i++)
! 317: free((char GPFAR *) (m[i] + ncl));
! 318: free((char GPFAR *) (m + nrl));
! 319: }
! 320:
! 321: /*
! 322: This routine takes a sub matrix and extends the number of rows and
! 323: columns for a new matrix
! 324: */
! 325: float GPFAR *GPFAR * extend_matrix(a, nrl, nrh, ncl, nch, srh, sch)
! 326: register float GPFAR *GPFAR * a;
! 327: register int nrl, nrh, ncl, nch;
! 328: register int srh, sch;
! 329: {
! 330: register int i;
! 331: register float GPFAR *GPFAR * m;
! 332:
! 333: m = (float GPFAR * GPFAR *) gp_realloc((void *) (a + nrl), (unsigned long) (srh - nrl + 1) * sizeof(float GPFAR *), "extend matrix");
! 334:
! 335: m -= nrl;
! 336:
! 337: if (sch != nch) {
! 338: for (i = nrl; i <= nrh; i++) { /* Copy and extend rows */
! 339: if (!(m[i] = extend_vector(m[i], ncl, nch, sch))) {
! 340: free_matrix(m, nrl, nrh, ncl, sch);
! 341: int_error("not enough memory to extend matrix", NO_CARET);
! 342: return NULL;
! 343: }
! 344: }
! 345: }
! 346: for (i = nrh + 1; i <= srh; i++) {
! 347: if (!(m[i] = (float GPFAR *) gp_alloc((unsigned long) (nch - ncl + 1) * sizeof(float), NULL))) {
! 348: free_matrix(m, nrl, i - 1, nrl, sch);
! 349: int_error("not enough memory to extend matrix", NO_CARET);
! 350: return NULL;
! 351: }
! 352: m[i] -= ncl;
! 353: }
! 354: return m;
! 355: }
! 356: /*
! 357: this routine carves a large matrix down to size
! 358: */
! 359: float GPFAR *GPFAR * retract_matrix(a, nrl, nrh, ncl, nch, srh, sch)
! 360: register float GPFAR *GPFAR * a;
! 361: register int nrl, nrh, ncl, nch;
! 362: register int srh, sch;
! 363: {
! 364: register int i;
! 365: register float GPFAR *GPFAR * m;
! 366:
! 367: for (i = srh + 1; i <= nrh; i++) {
! 368: free_vector(a[i], ncl, nch);
! 369: }
! 370:
! 371: m = (float GPFAR * GPFAR *) gp_realloc((void *) (a + nrl), (unsigned long) (srh - nrl + 1) * sizeof(float GPFAR *), "retract matrix");
! 372:
! 373: m -= nrl;
! 374:
! 375: if (sch != nch) {
! 376: for (i = nrl; i <= srh; i++)
! 377: if (!(m[i] = retract_vector(m[i], ncl, nch, sch))) { { /* Shrink rows */
! 378: free_matrix(m, nrl, srh, ncl, sch);
! 379: int_error("not enough memory to retract matrix", NO_CARET);
! 380: return NULL;
! 381: }
! 382: }
! 383: }
! 384: return m;
! 385: }
! 386:
! 387: float
! 388: GPFAR *GPFAR * convert_matrix(a, nrl, nrh, ncl, nch)
! 389: float GPFAR *a;
! 390: register int nrl, nrh, ncl, nch;
! 391:
! 392: /* allocate a float matrix m[nrl...nrh][ncl...nch] that points to the
! 393: matrix declared in the standard C manner as a[nrow][ncol], where
! 394: nrow=nrh-nrl+1, ncol=nch-ncl+1. The routine should be called with
! 395: the address &a[0][0] as the first argument. This routine does
! 396: not free the memory used by the original array a but merely assigns
! 397: pointers to the rows. */
! 398:
! 399: {
! 400: register int i, j, ncol, nrow;
! 401: register float GPFAR *GPFAR * m;
! 402:
! 403: nrow = nrh - nrl + 1;
! 404: ncol = nch - ncl + 1;
! 405: m = (float GPFAR * GPFAR *) gp_alloc((unsigned long) (nrh - nrl + 1) * sizeof(float GPFAR *), "convert_matrix");
! 406: m -= nrl;
! 407:
! 408: m[nrl] = a - ncl;
! 409: for (i = 1, j = nrl + 1; i <= nrow - 1; i++, j++)
! 410: m[j] = m[j - 1] + ncol;
! 411: return m;
! 412: }
! 413:
! 414:
! 415: void free_convert_matrix(b, nrl, nrh, ncl, nch)
! 416: float GPFAR *GPFAR * b;
! 417: register int nrl, nrh, ncl, nch;
! 418: {
! 419: free((char *) (b + nrl));
! 420: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>