/*
* Vis5D system for visualizing five dimensional gridded data sets.
* Copyright (C) 1990 - 2000 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 2 of the License, or
* (at your option) any later version.
*
* As a special exception to the terms of the GNU General Public
* License, you are permitted to link Vis5D with (and distribute the
* resulting source and executables) the LUI library (copyright by
* Stellar Computer Inc. and licensed for distribution with Vis5D),
* the McIDAS library, and/or the NetCDF library, where those
* libraries are governed by the terms of their own licenses.
*
* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
*/
#include "../config.h"
/*
* 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 the configure script detects 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 <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#ifdef _CRAY
# include <string.h>
#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 *) 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];
}
free( buffer );
return nread;
#else
int nread = read( f, iarray, n*2 );
if (nread<=0)
return 0;
#ifndef WORDS_BIGENDIAN
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 *) 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];
}
free( buffer );
return nread;
#else
int nread = read( f, iarray, n*2 );
if (nread<=0)
return 0;
#ifndef WORDS_BIGENDIAN
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 )
{
#ifndef WORDS_BIGENDIAN
/* 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 *) 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;
}
}
free( buffer );
return nread;
#else
int nread = read( f, iarray, 4*n );
if (nread<=0)
return 0;
# ifndef WORDS_BIGENDIAN
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
# ifndef WORDS_BIGENDIAN
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 *) 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 );
free( buffer );
return nread;
#else
int nread = read( f, x, 4*n );
if (nread<=0)
return 0;
#ifndef WORDS_BIGENDIAN
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) {
#ifndef WORDS_BIGENDIAN
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) {
#ifndef WORDS_BIGENDIAN
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;
#ifndef WORDS_BIGENDIAN
flip2( (const unsigned short *) iarray, (unsigned short *) iarray, n );
#endif
nwritten = write( f, iarray, 2*n );
#ifndef WORDS_BIGENDIAN
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 *) 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 );
free( buffer );
if (nwritten<=0)
return 0;
else
return nwritten/2;
#else
int nwritten;
#ifndef WORDS_BIGENDIAN
flip2( iarray, (unsigned short *) iarray, n );
#endif
nwritten = write( f, iarray, 2*n );
#ifndef WORDS_BIGENDIAN
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
# ifndef WORDS_BIGENDIAN
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 *) 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 );
free( buf );
if (nwritten<=0)
return 0;
else
return nwritten / 4;
#else
# ifndef WORDS_BIGENDIAN
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
# ifndef WORDS_BIGENDIAN
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 *) malloc( n*4 + 8 );
if (!buffer)
return 0;
cray_to_ieee_array( buffer, x, n );
nwritten = write( f, buffer, 4*n );
free( buffer );
if (nwritten<=0)
return 0;
else
return nwritten / 4;
#else
# ifndef WORDS_BIGENDIAN
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) {
#ifndef WORDS_BIGENDIAN
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) {
#ifndef WORDS_BIGENDIAN
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;
}
syntax highlighted by Code2HTML, v. 0.9.1