[BACK]Return to binary.c CVS log [TXT][DIR] Up to [local] / OpenXM_contrib / gnuplot

Annotation of OpenXM_contrib/gnuplot/binary.c, Revision 1.1.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>