Back to index

plt-scheme  4.2.1
pdfutils.c
Go to the documentation of this file.
00001 /* $Id: pdfutils.c,v 1.1 2004/03/01 20:54:50 cozmic Exp $
00002 
00003     pdf_utils.c
00004 
00005     Copyright (C) 1992, 1993, 1994, 1995
00006     Maurice LeBrun                 mjl@dino.ph.utexas.edu
00007     Institute for Fusion Studies   University of Texas at Austin
00008 
00009     This library is free software; you can redistribute it and/or
00010     modify it under the terms of the GNU Library General Public
00011     License as published by the Free Software Foundation; either
00012     version 2 of the License, or (at your option) any later version.
00013 
00014     This library is distributed in the hope that it will be useful,
00015     but WITHOUT ANY WARRANTY; without even the implied warranty of
00016     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00017     Library General Public License for more details.
00018 
00019     You should have received a copy of the GNU Library General Public
00020     License along with this library; if not, write to the Free
00021     Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
00022 
00023 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
00024 
00025     These functions do the low-level reading/writing of portable data files.
00026     Data can be written to/read from either a file handle or memory buffer.
00027 */
00028 
00029 #define NEED_PLDEBUG
00030 #include "plplotP.h"
00031 
00032 static void print_ieeef     (void *, void *);
00033 static int  pdf_wrx  (const U_CHAR *x, long nitems, PDFstrm *pdfs);
00034 
00035 static int debug = 0;
00036 
00037 /*--------------------------------------------------------------------------*\
00038  * void pdf_set (string, value)
00039  *
00040  * Set an option.  Pretty sparse right now but you never know.
00041 \*--------------------------------------------------------------------------*/
00042 
00043 void
00044 pdf_set(char *option, int value)
00045 {
00046     if ( ! strcmp(option, "debug"))
00047        debug = value;
00048 }
00049 
00050 /*--------------------------------------------------------------------------*\
00051  * pdf_fopen()
00052  *
00053  * Initializes a PDFstrm for a file oriented device.
00054  * Used exactly like fopen().
00055 \*--------------------------------------------------------------------------*/
00056 
00057 PDFstrm *
00058 pdf_fopen(char *filename, char *mode)
00059 {
00060     PDFstrm *pdfs;
00061 
00062     dbug_enter("pdf_fopen");
00063 
00064     pdfs = (PDFstrm *) malloc(sizeof(PDFstrm));
00065 
00066     if (pdfs != NULL) {
00067        pdfs->buffer = NULL;
00068        pdfs->file = NULL;
00069 #ifdef PLPLOT_USE_TCL_CHANNELS
00070        pdfs->tclChan = NULL;
00071        if (1) {
00072            char new_mode[3];
00073            int binary = 0;
00074            char *m, *p;
00075            
00076            /* Copy over the mode, removing 'b' if needed */
00077            for (m = mode, p = new_mode; *m != 0; m++) {
00078                if (*m == 'b') {
00079                    binary = 1;
00080                } else {
00081                   *p = *m;
00082                   p++;
00083                }
00084            }
00085            *p = 0;
00086            
00087            pdfs->tclChan = Tcl_OpenFileChannel(NULL, filename, new_mode, 0);
00088            if (pdfs->tclChan == NULL) {
00089               pdf_close(pdfs);
00090               pdfs = NULL;
00091            } else {
00092               if (binary) {
00093                   Tcl_SetChannelOption(NULL, pdfs->tclChan, "-translation", 
00094                                     "binary");
00095               }
00096            }
00097        }
00098 #else
00099        pdfs->file = fopen(filename, mode);
00100        if (pdfs->file == NULL) {
00101            pdf_close(pdfs);
00102            pdfs = NULL;
00103        }
00104 #endif
00105     }
00106 
00107     return pdfs;
00108 }
00109 
00110 /*--------------------------------------------------------------------------*\
00111  * pdf_bopen()
00112  *
00113  * Initializes a PDFstrm for reading/writing to a memory buffer.
00114  * If buffer is NULL, a standard buffer is allocated.
00115 \*--------------------------------------------------------------------------*/
00116 
00117 PDFstrm *
00118 pdf_bopen(U_CHAR *buffer, long bufmax)
00119 {
00120     PDFstrm *pdfs;
00121 
00122     dbug_enter("pdf_bopen");
00123 
00124     pdfs = (PDFstrm *) malloc(sizeof(PDFstrm));
00125 
00126     if (pdfs != NULL) {
00127        pdfs->file = NULL;
00128 #ifdef PLPLOT_USE_TCL_CHANNELS
00129        pdfs->tclChan = NULL;
00130 #endif
00131        pdfs->bp = 0;
00132 
00133        if (buffer == NULL) {
00134            if (bufmax > 0)
00135               pdfs->bufmax = bufmax;
00136            else
00137               pdfs->bufmax = 2048;
00138 
00139            pdfs->buffer = (U_CHAR *) malloc(pdfs->bufmax);
00140            if (pdfs->buffer == NULL) {
00141               pdf_close(pdfs);
00142               pdfs = NULL;
00143            }
00144        }
00145        else {
00146            pdfs->bufmax = bufmax;
00147            pdfs->buffer = buffer;
00148        }
00149     }
00150 
00151     return pdfs;
00152 }
00153 
00154 /*--------------------------------------------------------------------------*\
00155  * pdf_finit()
00156  *
00157  * Initializes a PDFstrm for a file oriented device.
00158  * Like pdf_fopen() but an existing file handle is specified.
00159 \*--------------------------------------------------------------------------*/
00160 
00161 PDFstrm *
00162 pdf_finit(FILE *file)
00163 {
00164     PDFstrm *pdfs;
00165 
00166     dbug_enter("pdf_finit");
00167 
00168     pdfs = (PDFstrm *) malloc(sizeof(PDFstrm));
00169 
00170     if (pdfs != NULL) {
00171        pdfs->buffer = NULL;
00172        pdfs->file = file;
00173 #ifdef PLPLOT_USE_TCL_CHANNELS
00174        pdfs->tclChan = NULL;
00175 #endif
00176        pdfs->bp = 0;
00177     }
00178 
00179     return pdfs;
00180 }
00181 
00182 /*--------------------------------------------------------------------------*\
00183  * pdf_close()
00184  *
00185  * Closes a PDFstrm.
00186  * Used exactly like fclose().
00187 \*--------------------------------------------------------------------------*/
00188 
00189 int
00190 pdf_close(PDFstrm *pdfs)
00191 {
00192     dbug_enter("pdf_close");
00193 
00194     if (pdfs != NULL) {
00195        if (pdfs->file != NULL) {
00196            fclose(pdfs->file);
00197 #ifdef PLPLOT_USE_TCL_CHANNELS
00198        } else if (pdfs->tclChan != NULL) {
00199            Tcl_Close(NULL, pdfs->tclChan);
00200 #endif
00201        } else if (pdfs->buffer != NULL) {
00202            free ((void *) pdfs->buffer);
00203        }
00204        free((void *) pdfs);
00205     }
00206     return 0;
00207 }
00208 
00209 /*--------------------------------------------------------------------------*\
00210  * int pdf_putc()
00211  *
00212  * Writes a single character.
00213 \*--------------------------------------------------------------------------*/
00214 
00215 int
00216 pdf_putc(int c, PDFstrm *pdfs)
00217 {
00218     int result = EOF;
00219 
00220     if (pdfs->file != NULL) {
00221        result = putc(c, pdfs->file);
00222        pdfs->bp++;
00223 #ifdef PLPLOT_USE_TCL_CHANNELS
00224     } else if (pdfs->tclChan != NULL) {
00225        result = Tcl_WriteChars(pdfs->tclChan, &c, 1);
00226        pdfs->bp++;
00227 #endif
00228     } else if (pdfs->buffer != NULL) {
00229        if (pdfs->bp >= pdfs->bufmax) {
00230            pldebug("pdf_putc",
00231                   "Increasing buffer to %d bytes\n", pdfs->bufmax);
00232            pdfs->bufmax += 512;
00233            pdfs->buffer = (U_CHAR *)
00234               realloc((void *) pdfs->buffer, pdfs->bufmax);
00235        }
00236        pdfs->buffer[pdfs->bp++] = c;
00237        result = c;
00238     }
00239     else
00240        plexit("pdf_putc: Illegal operation");
00241 
00242     return result;
00243 }
00244 
00245 /*--------------------------------------------------------------------------*\
00246  * int pdf_getc()
00247  *
00248  * Reads a single character.
00249 \*--------------------------------------------------------------------------*/
00250 
00251 int
00252 pdf_getc(PDFstrm *pdfs)
00253 {
00254     int result = EOF;
00255 
00256     if (pdfs->file != NULL) {
00257        result = getc(pdfs->file);
00258        pdfs->bp++;
00259 #ifdef PLPLOT_USE_TCL_CHANNELS
00260     } else if (pdfs->tclChan != NULL) {
00261        result = Tcl_Read(pdfs->tclChan, &result, 1);
00262        pdfs->bp++;
00263 #endif
00264     } else if (pdfs->buffer != NULL) {
00265        if (pdfs->bp < pdfs->bufmax)
00266            result = pdfs->buffer[pdfs->bp++];
00267     }
00268     else
00269        plexit("pdf_getc: Illegal operation");
00270 
00271     return result;
00272 }
00273 
00274 /*--------------------------------------------------------------------------*\
00275  * int pdf_ungetc()
00276  *
00277  * Push back the last command read.
00278 \*--------------------------------------------------------------------------*/
00279 
00280 int
00281 pdf_ungetc(int c, PDFstrm *pdfs)
00282 {
00283     int result = EOF;
00284 
00285     if (pdfs->file != NULL) {
00286        result = ungetc(c, pdfs->file);
00287        if (pdfs->bp > 0) 
00288            pdfs->bp--;
00289 #ifdef PLPLOT_USE_TCL_CHANNELS
00290     } else if (pdfs->tclChan != NULL) {
00291        result = Tcl_Ungets(pdfs->tclChan, &c, 1, 0);
00292        if (pdfs->bp > 0) 
00293            pdfs->bp--;
00294 #endif
00295     } else if (pdfs->buffer != NULL) {
00296        if (pdfs->bp > 0) {
00297            pdfs->buffer[--pdfs->bp] = c;
00298            result = c;
00299        }
00300     }
00301     else
00302        plexit("pdf_ungetc: Illegal operation");
00303 
00304     return result;
00305 }
00306 
00307 /*--------------------------------------------------------------------------*\
00308  * int pdf_wrx()
00309  *
00310  * Writes a record.
00311 \*--------------------------------------------------------------------------*/
00312 
00313 static int
00314 pdf_wrx(const U_CHAR *x, long nitems, PDFstrm *pdfs)
00315 {
00316     int i, result = 0;
00317 
00318     if (pdfs->file != NULL) {
00319        result = fwrite(x, 1, nitems, pdfs->file);
00320        pdfs->bp += nitems;
00321 #ifdef PLPLOT_USE_TCL_CHANNELS
00322     } else if (pdfs->tclChan != NULL) {
00323        result = Tcl_Write(pdfs->tclChan, x, nitems);
00324        pdfs->bp += nitems;
00325 #endif
00326     } else if (pdfs->buffer != NULL) {
00327        for (i = 0; i < nitems; i++) {
00328            if (pdfs->bp >= pdfs->bufmax) {
00329               pldebug("pdf_wrx",
00330                      "Increasing buffer to %d bytes\n", pdfs->bufmax);
00331               pdfs->bufmax += 512;
00332               pdfs->buffer = (U_CHAR *)
00333                   realloc((void *) (pdfs->buffer), pdfs->bufmax);
00334            }
00335            pdfs->buffer[pdfs->bp++] = x[i];
00336        }
00337        result = i;
00338     }
00339 
00340     return result;
00341 }
00342 
00343 /*--------------------------------------------------------------------------*\
00344  * int pdf_rdx()
00345  *
00346  * Reads a record.
00347 \*--------------------------------------------------------------------------*/
00348 
00349 int
00350 pdf_rdx(U_CHAR *x, long nitems, PDFstrm *pdfs)
00351 {
00352     int i, result = 0;
00353 
00354     if (pdfs->file != NULL) {
00355        result = fread(x, 1, nitems, pdfs->file);
00356        pdfs->bp += nitems;
00357 #ifdef PLPLOT_USE_TCL_CHANNELS
00358     } else if (pdfs->tclChan != NULL) {
00359        result = Tcl_ReadRaw(pdfs->tclChan, x, nitems);
00360        pdfs->bp += nitems;
00361 #endif
00362     } else if (pdfs->buffer != NULL) {
00363        for (i = 0; i < nitems; i++) {
00364            if (pdfs->bp > pdfs->bufmax)
00365               break;
00366            x[i] = pdfs->buffer[pdfs->bp++];
00367        }
00368        result = i;
00369     }
00370 
00371     return result;
00372 }
00373 
00374 /*--------------------------------------------------------------------------*\
00375  * pdf_wr_header()
00376  *
00377  * Writes a header string.  Input string must be NULL-terminated.  The
00378  * written string is terminated by a new-line, not a NULL.  This is done
00379  * so you can type e.g. "% strings <file> | head" and get sensible output.
00380 \*--------------------------------------------------------------------------*/
00381 
00382 int
00383 pdf_wr_header(PDFstrm *pdfs, char *header)
00384 {
00385     int i;
00386 
00387     dbug_enter("pdf_wr_header");
00388 
00389     for (i = 0; i < 79; i++) {
00390        if (header[i] == '\0')
00391            break;
00392        if (pdf_putc(header[i], pdfs) == EOF)
00393            return PDF_WRERR;
00394     }
00395     if (pdf_putc('\n', pdfs) == EOF)
00396        return PDF_WRERR;
00397 
00398     return 0;
00399 }
00400 
00401 /*--------------------------------------------------------------------------*\
00402  * int pdf_rd_header
00403  *
00404  * Reads a newline-terminated header string from PDFstrm *pdfs, and
00405  * converts to a usual NULL-terminated string.  80 chars maximum assumed.
00406 \*--------------------------------------------------------------------------*/
00407 
00408 int
00409 pdf_rd_header(PDFstrm *pdfs, char *header)
00410 {
00411     int i, c;
00412 
00413     dbug_enter("pdf_rd_header");
00414 
00415     for (i = 0; i < 79; i++) {
00416        if ((c = pdf_getc(pdfs)) == EOF)
00417            return PDF_RDERR;
00418 
00419        header[i] = c;
00420        if (header[i] == '\n')
00421            break;
00422     }
00423     header[i] = '\0';              /* NULL terminate */
00424     return 0;
00425 }
00426 
00427 /*--------------------------------------------------------------------------*\
00428  * pdf_wr_string()
00429  *
00430  * Writes a null-terminated string.
00431 \*--------------------------------------------------------------------------*/
00432 
00433 int
00434 pdf_wr_string(PDFstrm *pdfs, const char *string)
00435 {
00436     int i;
00437 
00438     dbug_enter("pdf_wr_string");
00439 
00440     for (i = 0; i <= strlen(string); i++) {
00441        if (pdf_putc(string[i], pdfs) == EOF)
00442            return PDF_WRERR;
00443     }
00444 
00445     return 0;
00446 }
00447 
00448 /*--------------------------------------------------------------------------*\
00449  * int pdf_rd_string
00450  *
00451  * Reads a null-terminated string from PDFstrm *pdfs.
00452  * A max of nmax chars are read.
00453 \*--------------------------------------------------------------------------*/
00454 
00455 int
00456 pdf_rd_string(PDFstrm *pdfs, char *string, int nmax)
00457 {
00458     int i, c;
00459 
00460     dbug_enter("pdf_rd_string");
00461 
00462     for (i = 0; i < nmax; i++) {
00463        if ((c = pdf_getc(pdfs)) == EOF)
00464            return PDF_RDERR;
00465 
00466        string[i] = c;
00467        if (c == '\0')
00468            break;
00469     }
00470     string[i] = '\0';              /* handle boundary case */
00471     return 0;
00472 }
00473 
00474 /*--------------------------------------------------------------------------*\
00475  * int pdf_wr_1byte()
00476  *
00477  * Writes a U_CHAR as a single byte.
00478 \*--------------------------------------------------------------------------*/
00479 
00480 int
00481 pdf_wr_1byte(PDFstrm *pdfs, U_CHAR s)
00482 {
00483     U_CHAR x[1];
00484 
00485     x[0] = s;
00486     if (pdf_wrx(x, 1, pdfs) != 1)
00487        return PDF_WRERR;
00488 
00489     return 0;
00490 }
00491 
00492 /*--------------------------------------------------------------------------*\
00493  * int pdf_rd_1byte()
00494  *
00495  * Reads a single byte, storing into a U_CHAR.
00496 \*--------------------------------------------------------------------------*/
00497 
00498 int
00499 pdf_rd_1byte(PDFstrm *pdfs, U_CHAR *ps)
00500 {
00501     U_CHAR x[1];
00502 
00503     if ( ! pdf_rdx(x, 1, pdfs))
00504        return PDF_RDERR;
00505 
00506     *ps = ((U_CHAR) x[0]);
00507     return 0;
00508 }
00509 
00510 /*--------------------------------------------------------------------------*\
00511  * pdf_wr_2bytes()
00512  *
00513  * Writes a U_SHORT as two single bytes, low end first.
00514 \*--------------------------------------------------------------------------*/
00515 
00516 int
00517 pdf_wr_2bytes(PDFstrm *pdfs, U_SHORT s)
00518 {
00519     U_CHAR x[2];
00520 
00521     x[0] = (U_CHAR) ((U_LONG) (s & (U_LONG) 0x00FF));
00522     x[1] = (U_CHAR) ((U_LONG) (s & (U_LONG) 0xFF00) >> 8);
00523 
00524     if (pdf_wrx(x, 2, pdfs) != 2)
00525        return PDF_WRERR;
00526 
00527     return 0;
00528 }
00529 
00530 /*--------------------------------------------------------------------------*\
00531  * pdf_rd_2bytes()
00532  *
00533  * Reads a U_SHORT from two single bytes, low end first.
00534 \*--------------------------------------------------------------------------*/
00535 
00536 int
00537 pdf_rd_2bytes(PDFstrm *pdfs, U_SHORT *ps)
00538 {
00539     U_CHAR x[2];
00540 
00541     if ( ! pdf_rdx(x, 2, pdfs))
00542        return PDF_RDERR;
00543 
00544     *ps = 0;
00545     *ps |= (U_LONG) x[0];
00546     *ps |= (U_LONG) x[1] << 8;
00547 
00548     return 0;
00549 }
00550 
00551 /*--------------------------------------------------------------------------*\
00552  * pdf_wr_2nbytes()
00553  *
00554  * Writes n U_SHORT's as 2n single bytes, low end first.
00555 \*--------------------------------------------------------------------------*/
00556 
00557 int
00558 pdf_wr_2nbytes(PDFstrm *pdfs, U_SHORT *s, PLINT n)
00559 {
00560     PLINT i;
00561     U_CHAR x[2];
00562 
00563     for (i = 0; i < n; i++) {
00564        x[0] = (U_CHAR) ((U_LONG) (s[i] & (U_LONG) 0x00FF));
00565        x[1] = (U_CHAR) ((U_LONG) (s[i] & (U_LONG) 0xFF00) >> 8);
00566 
00567        if (pdf_wrx(x, 2, pdfs) != 2)
00568            return PDF_WRERR;
00569     }
00570     return 0;
00571 }
00572 
00573 /*--------------------------------------------------------------------------*\
00574  * pdf_rd_2nbytes()
00575  *
00576  * Reads n U_SHORT's from 2n single bytes, low end first.
00577 \*--------------------------------------------------------------------------*/
00578 
00579 int
00580 pdf_rd_2nbytes(PDFstrm *pdfs, U_SHORT *s, PLINT n)
00581 {
00582     PLINT i;
00583     U_CHAR x[2];
00584 
00585     for (i = 0; i < n; i++) {
00586        if ( ! pdf_rdx(x, 2, pdfs))
00587            return PDF_RDERR;
00588 
00589        s[i] = 0;
00590        s[i] |= (U_SHORT) x[0];
00591        s[i] |= (U_SHORT) x[1] << 8;
00592     }
00593     return 0;
00594 }
00595 
00596 /*--------------------------------------------------------------------------*\
00597  * pdf_wr_4bytes()
00598  *
00599  * Writes an unsigned long as four single bytes, low end first.
00600 \*--------------------------------------------------------------------------*/
00601 
00602 int
00603 pdf_wr_4bytes(PDFstrm *pdfs, U_LONG s)
00604 {
00605     U_CHAR x[4];
00606 
00607     x[0] = (U_CHAR) ((s & (U_LONG) 0x000000FF));
00608     x[1] = (U_CHAR) ((s & (U_LONG) 0x0000FF00) >> 8);
00609     x[2] = (U_CHAR) ((s & (U_LONG) 0x00FF0000) >> 16);
00610     x[3] = (U_CHAR) ((s & (U_LONG) 0xFF000000) >> 24);
00611 
00612     if (pdf_wrx(x, 4, pdfs) != 4)
00613        return PDF_WRERR;
00614 
00615     return 0;
00616 }
00617 
00618 /*--------------------------------------------------------------------------*\
00619  * pdf_rd_4bytes()
00620  *
00621  * Reads an unsigned long from 4 single bytes, low end first.
00622 \*--------------------------------------------------------------------------*/
00623 
00624 int
00625 pdf_rd_4bytes(PDFstrm *pdfs, U_LONG *ps)
00626 {
00627     U_CHAR x[4];
00628 
00629     if ( ! pdf_rdx(x, 4, pdfs))
00630        return PDF_RDERR;
00631 
00632     *ps = 0;
00633     *ps |= (U_LONG) x[0];
00634     *ps |= (U_LONG) x[1] << 8;
00635     *ps |= (U_LONG) x[2] << 16;
00636     *ps |= (U_LONG) x[3] << 24;
00637 
00638     return 0;
00639 }
00640 
00641 /*--------------------------------------------------------------------------*\
00642  * Here is the IEEE floating point specification in both 32 bit and 64 bit
00643  * precisions, from page 9 of "IEEE Standard for Binary Floating-Point
00644  * Arithmetic", copyright 1985, IEEE Std 754-1985:
00645  * 
00646  * 
00647  *                             Single Format
00648  * 
00649  * msb means most significant bit
00650  * lsb means least significant bit
00651  * 
00652  *   1         8                                23
00653  * _____________________________________________________________________
00654  * |   |                |                                              |
00655  * | s |       e        |                        f                     |
00656  * |___|________________|______________________________________________|
00657  *      msb          lsb msb                                        lsb
00658  * 
00659  * 
00660  * 
00661  *                             Double Format
00662  * 
00663  * msb means most significant bit
00664  * lsb means least significant bit
00665  * 
00666  *   1        11                                52
00667  * _____________________________________________________________________
00668  * |   |                |                                              |
00669  * | s |       e        |                        f                     |
00670  * |___|________________|______________________________________________|
00671  *      msb          lsb msb                                        lsb
00672  * 
00673  * 
00674  * (Thanks to: Andy Mai (mai@ncar.ucar.edu))
00675  * 
00676  * 
00677  * According to "inmos: Transputer instruction set" the IEEE standard
00678  * specifies the floating format as:
00679  * 
00680  *      s exp frac
00681  * 
00682  * Where: s = sign bit  (1 bit)
00683  *      exp = exponent (8 bits for 32 bit float / 11 bits for 64 bit float)
00684  *      frac = fraction (23 bits for 32 bit float / 52 bits for 64 bit float)
00685  * 
00686  * value of (s exp frac) = (-1)^s * 1.frac * 2^(exp-bias) ; if exp not 0
00687  *                         (-1)^s * 0.frac * 2^(1-bias) ; if exp = 0
00688  * 
00689  * where bias = 127 for 32 bit float
00690  *       bias = 1023 for 64 bit float
00691  * 
00692  * (Thanks to: Tom Bjorkholm(TBJORKHOLM@abo.fi))
00693  * 
00694 \*--------------------------------------------------------------------------*/
00695 
00696 /*--------------------------------------------------------------------------*\
00697  * int pdf_wr_ieeef()
00698  *
00699  * Writes a float in IEEE single precision (32 bit) format.
00700 \*--------------------------------------------------------------------------*/
00701 
00702 int
00703 pdf_wr_ieeef(PDFstrm *pdfs, float f)
00704 {
00705     double fdbl, fmant, f_new;
00706     float fsgl, f_tmp;
00707     int istat, exp, e_new, e_off, bias = 127;
00708     U_LONG value, s_ieee, e_ieee, f_ieee;
00709 
00710     if (f == 0.0) {
00711        value = 0;
00712        return (pdf_wr_4bytes(pdfs, value));
00713     }
00714     fsgl = fdbl = f;
00715     fmant = frexp(fdbl, &exp);
00716 
00717     if (fmant < 0)
00718        s_ieee = 1;
00719     else
00720        s_ieee = 0;
00721 
00722     fmant = fabs(fmant);
00723     f_new = 2 * fmant;
00724     e_new = exp - 1;
00725 
00726     if (e_new < 1 - bias) {
00727        e_off = e_new - (1 - bias);
00728        e_ieee = 0;
00729        f_tmp = f_new * pow((double) 2.0, (double) e_off);
00730     }
00731     else {
00732        e_ieee = e_new + bias;
00733        f_tmp = f_new - 1;
00734     }
00735     f_ieee = f_tmp * 8388608;             /* multiply by 2^23 */
00736 
00737     if (e_ieee > 255) {
00738        if (debug)
00739            fprintf(stderr, "pdf_wr_ieeef: Warning -- overflow\n");
00740        e_ieee = 255;
00741     }
00742 
00743     s_ieee = s_ieee << 31;
00744     e_ieee = e_ieee << 23;
00745 
00746     value = s_ieee | e_ieee | f_ieee;
00747 
00748     if ((istat = pdf_wr_4bytes(pdfs, value)))
00749        return (istat);
00750 
00751     if (debug) {
00752        fprintf(stderr, "Float value (written):      %g\n", fsgl);
00753        print_ieeef(&fsgl, &value);
00754     }
00755 
00756     return 0;
00757 }
00758 
00759 /*--------------------------------------------------------------------------*\
00760  * int pdf_rd_ieeef()
00761  *
00762  * Reads a float from a IEEE single precision (32 bit) format.
00763 \*--------------------------------------------------------------------------*/
00764 
00765 int
00766 pdf_rd_ieeef(PDFstrm *pdfs, float *pf)
00767 {
00768     double f_new, f_tmp;
00769     float fsgl;
00770     int istat, exp, bias = 127;
00771     U_LONG value, s_ieee, e_ieee, f_ieee;
00772 
00773     if ((istat = pdf_rd_4bytes(pdfs, &value)))
00774        return (istat);
00775 
00776     s_ieee = (value & (U_LONG) 0x80000000) >> 31;
00777     e_ieee = (value & (U_LONG) 0x7F800000) >> 23;
00778     f_ieee = (value & (U_LONG) 0x007FFFFF);
00779 
00780     f_tmp = (double) f_ieee / 8388608.0;  /* divide by 2^23 */
00781 
00782     if (e_ieee == 0) {
00783        exp = 1 - bias;
00784        f_new = f_tmp;
00785     }
00786     else {
00787        exp = (int) e_ieee - bias;
00788        f_new = 1.0 + f_tmp;
00789     }
00790 
00791     fsgl = f_new * pow(2.0, (double) exp);
00792     if (s_ieee == 1)
00793        fsgl = -fsgl;
00794 
00795     *pf = fsgl;
00796 
00797     if (debug) {
00798        fprintf(stderr, "Float value (read):      %g\n", fsgl);
00799        print_ieeef(&fsgl, &value);
00800     }
00801 
00802     return 0;
00803 }
00804 
00805 /*--------------------------------------------------------------------------*\
00806  * print_ieeef()
00807  *
00808  * Prints binary representation for numbers pointed to by arguments.
00809  * The first argument is the original float, the second is the
00810  * IEEE representation.  They should be the same on any machine that
00811  * uses IEEE floats.
00812 \*--------------------------------------------------------------------------*/
00813 
00814 static void
00815 print_ieeef(void *vx, void *vy)
00816 {
00817     int i;
00818     U_LONG f, *x = (U_LONG *) vx, *y = (U_LONG *) vy;
00819     char bitrep[33];
00820 
00821     bitrep[32] = '\0';
00822 
00823     f = *x;
00824     for (i = 0; i < 32; i++) {
00825        if (f & 1)
00826            bitrep[32 - i - 1] = '1';
00827        else
00828            bitrep[32 - i - 1] = '0';
00829        f = f >> 1;
00830     }
00831     fprintf(stderr, "Binary representation:      ");
00832     fprintf(stderr, "%s\n", bitrep);
00833 
00834     f = *y;
00835     for (i = 0; i < 32; i++) {
00836        if (f & 1)
00837            bitrep[32 - i - 1] = '1';
00838        else
00839            bitrep[32 - i - 1] = '0';
00840        f = f >> 1;
00841     }
00842     fprintf(stderr, "Converted representation:   ");
00843     fprintf(stderr, "%s\n\n", bitrep);
00844 
00845     return;
00846 }
00847 
00848 /*--------------------------------------------------------------------------*\
00849  * plAlloc2dGrid()
00850  *
00851  * Allocates a block of memory for use as a 2-d grid of PLFLT's.
00852  * Resulting array can be indexed as f[i][j] anywhere.  This is to be used
00853  * instead of PLFLT f[nx][ny], which is less useful.  Note that this type
00854  * of allocation is required by the PLplot functions which take a 2-d
00855  * grids of PLFLT's as an argument, such as plcont() and plot3d().
00856  * Example usage:
00857  *
00858  *   PLFLT **z;
00859  *
00860  *   Alloc2dGrid(&z, XPTS, YPTS);
00861 \*--------------------------------------------------------------------------*/
00862 
00863 void
00864 plAlloc2dGrid(PLFLT ***f, PLINT nx, PLINT ny)
00865 {
00866     PLINT i;
00867 
00868     if ((*f = (PLFLT **) calloc(nx, sizeof(PLFLT *)))==NULL)
00869         plexit("Memory allocation error in \"plAlloc2dGrid\"");
00870 
00871     for (i = 0; i < nx; i++) {
00872        if (((*f)[i] = (PLFLT *) calloc(ny ,sizeof(PLFLT)))==NULL)
00873           plexit("Memory allocation error in \"plAlloc2dGrid\"");
00874     }
00875 
00876 }
00877 
00878 /*--------------------------------------------------------------------------*\
00879  * Free2dGrid()
00880  *
00881  * Frees a block of memory allocated with Alloc2dGrid().
00882 \*--------------------------------------------------------------------------*/
00883 
00884 void
00885 plFree2dGrid(PLFLT **f, PLINT nx, PLINT ny)
00886 {
00887     PLINT i;
00888 
00889     for (i = 0; i < nx; i++)
00890        free((void *) f[i]);
00891 
00892     free((void *) f);
00893 }
00894 
00895 /*--------------------------------------------------------------------------*\
00896  * MinMax2dGrid()
00897  *
00898  * Finds the maximum and minimum of a 2d matrix allocated with plAllc2dGrid().
00899 \*--------------------------------------------------------------------------*/
00900 
00901 void
00902 plMinMax2dGrid(PLFLT **f, PLINT nx, PLINT ny, PLFLT *fmax, PLFLT *fmin)
00903 {
00904     int i, j;
00905     PLFLT m, M;
00906 
00907     M = m = f[0][0];
00908 
00909     for (i = 0; i < nx; i++) {
00910        for (j = 0; j < ny; j++) {
00911            if (f[i][j] > M) M = f[i][j];
00912            if (f[i][j] < m) m = f[i][j];
00913        }
00914     }
00915     *fmax = M;
00916     *fmin = m;
00917 }