PLplot 5.9.6
|
00001 /* $Id$ 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 General Library 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( 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 }