Annotation of OpenXM_contrib/gnuplot/binary.c, Revision 1.1.1.3
1.1 maekawa 1: #ifndef lint
1.1.1.3 ! ohara 2: static char *RCSid = "$Id: binary.c,v 1.4.2.1 2002/01/31 21:18:21 lhecking Exp $";
1.1 maekawa 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:
1.1.1.3 ! ohara 215: if (!(vec = (float GPFAR *) gp_alloc((nh - nl + 1) * sizeof(float), NULL))) {
1.1 maekawa 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:
1.1.1.3 ! ohara 289: m = (float GPFAR * GPFAR *) gp_alloc((nrh - nrl + 1) * sizeof(float GPFAR *), "matrix");
1.1 maekawa 290: m -= nrl;
291:
292: for (i = nrl; i <= nrh; i++) {
1.1.1.3 ! ohara 293: if (!(m[i] = (float GPFAR *) gp_alloc((nch - ncl + 1) * sizeof(float), NULL))) {
1.1 maekawa 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++) {
1.1.1.3 ! ohara 347: if (!(m[i] = (float GPFAR *) gp_alloc((nch - ncl + 1) * sizeof(float), NULL))) {
1.1 maekawa 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;
1.1.1.3 ! ohara 405: m = (float GPFAR * GPFAR *) gp_alloc((nrh - nrl + 1) * sizeof(float GPFAR *), "convert_matrix");
1.1 maekawa 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>