home *** CD-ROM | disk | FTP | other *** search
/ CICA 1995 May / cica_0595_4.zip / cica_0595_4 / UTIL / GPT34SRC / BINARY.C < prev    next >
C/C++ Source or Header  |  1993-05-25  |  14KB  |  491 lines

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