• Main Page
  • Namespaces
  • Classes
  • Files
  • File List
  • File Members

pdfutils.c

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

Generated on Wed Oct 12 2011 20:42:22 for PLplot by  doxygen 1.7.1