/* Vis5D version 5.0 */ /* Vis5D system for visualizing five dimensional gridded data sets Copyright (C) 1990 - 1997 Bill Hibbard, Johan Kellum, Brian Paul, Dave Santek, and Andre Battaiola. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 1, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ /* * Functions to do binary I/O of floats, ints. * * >>>> These functions are built on top of Unix I/O functions, not stdio! <<<< * * The file format is assumed to be BIG-ENDIAN. * If this code is compiled with -DLITTLE and executes on a little endian * CPU then byte-swapping will be done. * * If an ANSI compiler is used prototypes and ANSI function declarations * are used. Otherwise use K&R conventions. * * If we're running on a CRAY (8-byte ints and floats), conversions will * be done as needed. */ /* * Updates: * * April 13, 1995, brianp * added cray_to_ieee and iee_to_cray array conversion functions. * fixed potential cray bug in write_float4_array function. * */ #include #include #include #ifdef _CRAY # include #include #endif #include "binio.h" /**********************************************************************/ /****** Byte Flipping *****/ /**********************************************************************/ #define FLIP4( n ) ( (n & 0xff000000) >> 24 \ | (n & 0x00ff0000) >> 8 \ | (n & 0x0000ff00) << 8 \ | (n & 0x000000ff) << 24 ) #define FLIP2( n ) (((unsigned short) (n & 0xff00)) >> 8 | (n & 0x00ff) << 8) /* * Flip the order of the 4 bytes in an array of 4-byte words. */ void flip4(const unsigned int *src, unsigned int *dest, int n) { int i; for (i = 0; i < n; i++) { unsigned int tmp = src[i]; dest[i] = FLIP4(tmp); } } /* * Flip the order of the 2 bytes in an array of 2-byte words. */ void flip2(const unsigned short *src, unsigned short *dest, int n) { int i; for (i = 0; i < n; i++) { unsigned short tmp = src[i]; dest[i] = FLIP2(tmp); } } #ifdef _CRAY /***************************************************************************** * * The following source code is in the public domain. * Specifically, we give to the public domain all rights for future licensing * of the source code, all resale rights, and all publishing rights. * * We ask, but do not require, that the following message be included in all * derived works: * * Portions developed at the National Center for Supercomputing Applications at * the University of Illinois at Urbana-Champaign. * * THE UNIVERSITY OF ILLINOIS GIVES NO WARRANTY, EXPRESSED OR IMPLIED, FOR THE * SOFTWARE AND/OR DOCUMENTATION PROVIDED, INCLUDING, WITHOUT LIMITATION, * WARRANTY OF MERCHANTABILITY AND WARRANTY OF FITNESS FOR A PARTICULAR PURPOSE * ****************************************************************************/ /** THESE ROUTINES MUST BE COMPILED ON THE CRAY ONLY SINCE THEY **/ /** REQUIRE 8-BYTES PER C-TYPE LONG **/ /* Cray to IEEE single precision */ static void c_to_if(long *t, const long *f) { if (*f != 0) { *t = (((*f & 0x8000000000000000) | /* sign bit */ ((((*f & 0x7fff000000000000) >> 48) - 16258) << 55)) + /* exp */ (((*f & 0x00007fffff000000) + ((*f & 0x0000000000800000) << 1)) << 8)); /* mantissa */ } else *t = *f; } #define C_TO_IF( T, F ) \ if (F != 0) { \ T = (((F & 0x8000000000000000) | \ ((((F & 0x7fff000000000000) >> 48)-16258) << 55)) + \ (((F & 0x00007fffff000000) + \ ((F & 0x0000000000800000) << 1)) << 8)); \ } \ else { \ T = F; \ } /* IEEE single precison to Cray */ static void if_to_c(long *t, const long *f) { if (*f != 0) { *t = (((*f & 0x8000000000000000) | ((*f & 0x7f80000000000000) >> 7) + (16258 << 48)) | (((*f & 0x007fffff00000000) >> 8) | (0x0000800000000000))); if ((*f << 1) == 0) *t = 0; } else *t = *f; } /* T and F must be longs! */ #define IF_TO_C( T, F ) \ if (F != 0) { \ T = (((F & 0x8000000000000000) | \ ((F & 0x7f80000000000000) >> 7) + \ (16258 << 48)) | \ (((F & 0x007fffff00000000) >> 8) | (0x0000800000000000))); \ if ((F << 1) == 0) T = 0; \ } \ else { \ T = F; \ } /* * Convert an array of Cray 8-byte floats to an array of IEEE 4-byte floats. */ void cray_to_ieee_array(long *dest, const float *source, int n) { long *dst; const long *src; long tmp1, tmp2; int i; dst = dest; src = (const long *)source; for (i = 0; i < n; i += 2) { /* add 1 in case n is odd */ c_to_if(&tmp1, &src[i]); c_to_if(&tmp2, &src[i + 1]); *dst = (tmp1 & 0xffffffff00000000) | (tmp2 >> 32); dst++; } } /* * Convert an array of IEEE 4-byte floats to an array of 8-byte Cray floats. */ void ieee_to_cray_array(float *dest, const long *source, int n) { long *dst; const long *src; int i; long ieee; src = source; dst = (long *)dest; for (i = 0; i < n; i++) { /* most significant 4-bytes of ieee contain bit pattern to convert */ if ((i & 1) == 0) { /* get upper half */ ieee = src[i / 2] & 0xffffffff00000000; } else { /* get lower half */ ieee = src[i / 2] << 32; } if_to_c(dst, &ieee); dst++; } } #endif /*_CRAY*/ /**********************************************************************/ /***** Read Functions *****/ /**********************************************************************/ /* * Read a block of bytes. * Input: f - the file descriptor to read from. * b - address of buffer to read into. * n - number of bytes to read. * Return: number of bytes read, 0 if error. */ int read_bytes(int f, void *b, int n) { return read(f, b, n); } /* * Read an array of 2-byte integers. * Input: f - file descriptor * iarray - address to put integers * n - number of integers to read. * Return: number of integers read. */ int read_int2_array(int f, short *iarray, int n) { #ifdef _CRAY int i; signed char *buffer; int nread; buffer = (signed char *)G_malloc(n * 2); if (!buffer) return 0; nread = read(f, buffer, n * 2); if (nread <= 0) return 0; nread /= 2; for (i = 0; i < nread; i++) { /* don't forget about sign extension! */ iarray[i] = (buffer[i * 2] * 256) | buffer[i * 2 + 1]; } G_free(buffer); return nread; #else int nread = read(f, iarray, n * 2); if (nread <= 0) return 0; #ifdef LITTLE flip2((const unsigned short *)iarray, (unsigned short *)iarray, nread / 2); #endif return nread / 2; #endif } /* * Read an array of unsigned 2-byte integers. * Input: f - file descriptor * iarray - address to put integers * n - number of integers to read. * Return: number of integers read. */ int read_uint2_array(int f, unsigned short *iarray, int n) { #ifdef _CRAY int i; unsigned char *buffer; int nread; buffer = (unsigned char *)G_malloc(n * 2); if (!buffer) return 0; nread = read(f, buffer, n * 2); if (nread <= 0) return 0; nread /= 2; for (i = 0; i < nread; i++) { iarray[i] = (buffer[i * 2] << 8) | buffer[i * 2 + 1]; } G_free(buffer); return nread; #else int nread = read(f, iarray, n * 2); if (nread <= 0) return 0; #ifdef LITTLE flip2(iarray, iarray, nread / 2); #endif return nread / 2; #endif } /* * Read a 4-byte integer. * Input: f - the file descriptor to read from * i - pointer to integer to put result into. * Return: 1 = ok, 0 = error */ int read_int4(int f, int *i) { #ifdef LITTLE /* read big endian and convert to little endian */ unsigned int n; if (read(f, &n, 4) == 4) { *i = FLIP4(n); return 1; } else { return 0; } #else if (read(f, i, 4) == 4) { # ifdef _CRAY *i = *i >> 32; # endif return 1; } else { return 0; } #endif } /* * Read an array of 4-byte integers. * Input: f - file descriptor * iarray - address to put integers * n - number of integers to read. * Return: number of integers read. */ int read_int4_array(int f, int *iarray, int n) { #ifdef _CRAY int j, nread; int *buffer; buffer = (int *)G_malloc((n + 1) * 4); if (!buffer) return 0; nread = read(f, buffer, 4 * n); if (nread <= 0) { return 0; } nread /= 4; for (j = 0; j < nread; j++) { if ((j & 1) == 0) { iarray[j] = buffer[j / 2] >> 32; } else { iarray[j] = buffer[j / 2] & 0xffffffff; } } G_free(buffer); return nread; #else int nread = read(f, iarray, 4 * n); if (nread <= 0) return 0; # ifdef LITTLE flip4((const unsigned int *)iarray, (unsigned int *)iarray, nread / 4); # endif return nread / 4; #endif } /* * Read a 4-byte IEEE float. * Input: f - the file descriptor to read from. * x - pointer to float to put result into. * Return: 1 = ok, 0 = error */ int read_float4(int f, float *x) { #ifdef _CRAY long buffer = 0; if (read(f, &buffer, 4) == 4) { /* convert IEEE float (buffer) to Cray float (x) */ if_to_c((long *)x, &buffer); return 1; } return 0; #else # ifdef LITTLE unsigned int n, *iptr; if (read(f, &n, 4) == 4) { iptr = (unsigned int *)x; *iptr = FLIP4(n); return 1; } else { return 0; } # else if (read(f, x, 4) == 4) { return 1; } else { return 0; } # endif #endif } /* * Read an array of 4-byte IEEE floats. * Input: f - file descriptor * x - address to put floats * n - number of floats to read. * Return: number of floats read. */ int read_float4_array(int f, float *x, int n) { #ifdef _CRAY /* read IEEE floats into buffer, then convert to Cray format */ long *buffer; int i, nread; buffer = (long *)G_malloc((n + 1) * 4); if (!buffer) return 0; nread = read(f, buffer, n * 4); if (nread <= 0) return 0; nread /= 4; ieee_to_cray_array(x, buffer, nread); G_free(buffer); return nread; #else int nread = read(f, x, 4 * n); if (nread <= 0) return 0; #ifdef LITTLE flip4((const unsigned int *)x, (unsigned int *)x, nread / 4); #endif return nread / 4; #endif } /* * Read a block of memory. * Input: f - file descriptor * data - address of first byte * elements - number of elements to read * elsize - size of each element to read (1, 2 or 4) * Return: number of elements written */ int read_block(int f, void *data, int elements, int elsize) { if (elsize == 1) { return read(f, data, elements); } else if (elsize == 2) { #ifdef LITTLE int n; n = read(f, data, elements * 2) / 2; if (n == elements) { flip2((const unsigned short *)data, (unsigned short *)data, elements); } return n; #else return read(f, data, elements * 2) / 2; #endif } else if (elsize == 4) { #ifdef LITTLE int n; n = read(f, data, elements * 4) / 4; if (n == elements) { flip4((const unsigned int *)data, (unsigned int *)data, elements); } return n; #else return read(f, data, elements * 4) / 4; #endif } else { printf("Fatal error in read_block(): bad elsize (%d)\n", elsize); abort(); } return 0; } /**********************************************************************/ /***** Write Functions *****/ /**********************************************************************/ /* * Write a block of bytes. * Input: f - the file descriptor to write to. * b - address of buffer to write. * n - number of bytes to write. * Return: number of bytes written, 0 if error. */ int write_bytes(int f, const void *b, int n) { return write(f, b, n); } /* * Write an array of 2-byte integers. * Input: f - file descriptor * iarray - address to put integers * n - number of integers to write. * Return: number of integers written */ int write_int2_array(int f, const short *iarray, int n) { #ifdef _CRAY printf("write_int2_array not implemented!\n"); exit(1); #else int nwritten; #ifdef LITTLE flip2((const unsigned short *)iarray, (unsigned short *)iarray, n); #endif nwritten = write(f, iarray, 2 * n); #ifdef LITTLE flip2((const unsigned short *)iarray, (unsigned short *)iarray, n); #endif if (nwritten <= 0) return 0; return nwritten / 2; #endif } /* * Write an array of 2-byte unsigned integers. * Input: f - file descriptor * iarray - address to put integers * n - number of integers to write. * Return: number of integers written */ int write_uint2_array(int f, const unsigned short *iarray, int n) { #ifdef _CRAY int i, nwritten; unsigned char *buffer; buffer = (unsigned char *)G_malloc(2 * n); if (!buffer) return 0; for (i = 0; i < n; i++) { buffer[i * 2] = (iarray[i] >> 8) & 0xff; buffer[i * 2 + 1] = iarray[i] & 0xff; } nwritten = write(f, buffer, 2 * n); G_free(buffer); if (nwritten <= 0) return 0; else return nwritten / 2; #else int nwritten; #ifdef LITTLE flip2(iarray, (unsigned short *)iarray, n); #endif nwritten = write(f, iarray, 2 * n); #ifdef LITTLE flip2(iarray, (unsigned short *)iarray, n); #endif if (nwritten <= 0) return 0; else return nwritten / 2; #endif } /* * Write a 4-byte integer. *Input: f - the file descriptor * i - the integer * Return: 1 = ok, 0 = error */ int write_int4(int f, int i) { #ifdef _CRAY i = i << 32; return write(f, &i, 4) > 0; #else # ifdef LITTLE i = FLIP4(i); # endif return write(f, &i, 4) > 0; #endif } /* * Write an array of 4-byte integers. * Input: f - the file descriptor * i - the array of ints * n - the number of ints in array * Return: number of integers written. */ int write_int4_array(int f, const int *i, int n) { #ifdef _CRAY int j, nwritten; char *buf, *b, *ptr; b = buf = (char *)G_malloc(n * 4 + 8); if (!b) return 0; ptr = (char *)i; for (j = 0; j < n; j++) { ptr += 4; /* skip upper 4 bytes */ *b++ = *ptr++; *b++ = *ptr++; *b++ = *ptr++; *b++ = *ptr++; } nwritten = write(f, buf, 4 * n); G_free(buf); if (nwritten <= 0) return 0; else return nwritten / 4; #else # ifdef LITTLE int nwritten; flip4((const unsigned int *)i, (unsigned int *)i, n); nwritten = write(f, i, 4 * n); flip4((const unsigned int *)i, (unsigned int *)i, n); if (nwritten <= 0) return 0; else return nwritten / 4; # else return write(f, i, 4 * n) / 4; # endif #endif } /* * Write a 4-byte IEEE float. * Input: f - the file descriptor * x - the float * Return: 1 = ok, 0 = error */ int write_float4(int f, float x) { #ifdef _CRAY char buffer[8]; c_to_if((long *)buffer, (const long *)&x); return write(f, buffer, 4) > 0; #else # ifdef LITTLE float y; unsigned int *iptr = (unsigned int *)&y, temp; y = (float)x; temp = FLIP4(*iptr); return write(f, &temp, 4) > 0; # else float y; y = (float)x; return write(f, &y, 4) > 0; # endif #endif } /* * Write an array of 4-byte IEEE floating point numbers. * Input: f - the file descriptor * x - the array of floats * n - number of floats in array * Return: number of float written. */ int write_float4_array(int f, const float *x, int n) { #ifdef _CRAY /* convert cray floats to IEEE and put into buffer */ int nwritten; long *buffer; buffer = (long *)G_malloc(n * 4 + 8); if (!buffer) return 0; cray_to_ieee_array(buffer, x, n); nwritten = write(f, buffer, 4 * n); G_free(buffer); if (nwritten <= 0) return 0; else return nwritten / 4; #else # ifdef LITTLE int nwritten; flip4((const unsigned int *)x, (unsigned int *)x, n); nwritten = write(f, x, 4 * n); flip4((const unsigned int *)x, (unsigned int *)x, n); if (nwritten <= 0) return 0; else return nwritten / 4; # else return write(f, x, 4 * n) / 4; # endif #endif } /* * Write a block of memory. * Input: f - file descriptor * data - address of first byte * elements - number of elements to write * elsize - size of each element to write (1, 2 or 4) * Return: number of elements written */ int write_block(int f, const void *data, int elements, int elsize) { if (elsize == 1) { return write(f, data, elements); } else if (elsize == 2) { #ifdef LITTLE int n; flip2((const unsigned short *)data, (unsigned short *)data, elements); n = write(f, data, elements * 2) / 2; flip2((const unsigned short *)data, (unsigned short *)data, elements); return n; #else return write(f, data, elements * 2) / 2; #endif } else if (elsize == 4) { #ifdef LITTLE int n; flip4((const unsigned int *)data, (unsigned int *)data, elements); n = write(f, data, elements * 4) / 4; flip4((const unsigned int *)data, (unsigned int *)data, elements); return n; #else return write(f, data, elements * 4) / 4; #endif } else { printf("Fatal error in write_block(): bad elsize (%d)\n", elsize); abort(); } return 0; }