home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
vis-ftp.cs.umass.edu
/
vis-ftp.cs.umass.edu.tar
/
vis-ftp.cs.umass.edu
/
pub
/
Software
/
ASCENDER
/
ascendMar8.tar
/
UMass
/
BoldtNew
/
LLVS
/
read_write_plane.c
< prev
next >
Wrap
C/C++ Source or Header
|
1996-01-31
|
24KB
|
748 lines
/* -*-c-mode-*- */
/*------------------------------------------------------
* READ_WRITE_PLANE.C - Generic C code to read and write LLVS planes
* Robert Heller Created on Mon Jul 10 09:46:28 1989
* Last mod -
*--------------------------------------------------------
* Contents:
*--------------------------------------------------------
* (c) Copyright 1989 by The University of Massachusetts
*------------------------------------------------------*/
#include <stdio.h> /* standard I/O defs */
#include <math.h> /* math defs */
#include <ctype.h> /* character defs */
#include <llvs_per_plane.h> /* llvs per_plane defs */
#include <llvs_plane.h> /* llvs plane file defs */
/*
* read_plane(plane,plane_info,associations,filename) - read in a plane file.
* plane is a pointer to a pointer to a PLANE object, plane_info is a pointer
* to a pointer to a PLANE_INFO object, associations is a pointer to a pointer
* to char, and filename is a filename.
* plane, plane_info, and associations are set to malloc'ed space, so should
* be addresses of cloberable pointers (i.e. addresses of variables or
* structure fields, etc.).
*/
char *malloc(), *calloc();
read_plane(plane,plane_info,associations,filename)
PLANE **plane;
PLANE_INFO **plane_info;
char **associations;
char *filename;
{
/* plane file header record structure */
static LLVS_PLANE_FILE_HEADER header;
/* plane size header record structure */
static LLVS_PLANE_SIZE_HEADER size_header;
int plsize; /* # bytes in plane */
FILE *plfile; /* plane file */
llvs_ubyte *data_pointer; /* pointer to data buffer */
int rbytes, bytesleft; /* I/O byte counters */
int need_swap, need_cvt_float; /* flags to indicate if conversions needed */
/* open file. abort if open failure */
plfile = fopen(filename,"r");
if (plfile == NULL) return(-1);
/* read header record */
if (fread(&header,32,1,plfile) != 1) return(-1);
#ifdef DECSTATION
if (header.ptype == 32) {
rewind(plfile);
return(read_plane_vms_var(plane,plane_info,associations,plfile));
}
#endif
need_swap = header.bsex != LLVS_NATIVE_BYTE_SEX;
need_cvt_float = header.floatfmt != LLVS_NATIVE_FLOATFMT;
if (need_swap) swap_longs(&header.pl_level,7);
if (header.ptype == LLVS_PLF_FLOAT && need_cvt_float)
cvt_floats(&header.background,1,header.floatfmt,LLVS_NATIVE_FLOATFMT);
/* computer plane size */
plsize = header.data_length - 12;
/* allocate plane info struct */
*plane_info = (PLANE_INFO *) malloc(sizeof(PLANE_INFO));
if (*plane_info == NULL) return(-1);
/* fill in plane info slots */
(*plane_info)->datatype = header.ptype;
(*plane_info)->level = header.pl_level;
(*plane_info)->row_location = header.row_location;
(*plane_info)->column_location = header.col_location;
(*plane_info)->background.fixnum = header.background.iback;
/* allocate plane it self */
*plane = (PLANE *) malloc(plsize);
if (*plane == NULL) return(-1);
/* allocate space for association list */
*associations = calloc(header.alist_length+1,sizeof(char));
if (*associations == NULL) return(-1);
/* read in association list */
data_pointer = (llvs_ubyte *) *associations; /* start of buffer */
bytesleft = header.alist_length; /* number of bytes to read */
while (bytesleft > 0) {
rbytes = bytesleft;
if (rbytes > BLOCKSIZE) rbytes = BLOCKSIZE;
if (fread(data_pointer,rbytes,1,plfile) != 1) return(-1);
data_pointer += rbytes;
bytesleft -= rbytes;
}
/* read size header */
if (fread(&size_header,12,1,plfile) != 1) return(-1);
if (need_swap) swap_longs(&size_header,3);
/* fill in addition slots in plane info */
(*plane_info)->row_dimension = size_header.row_dimension;
(*plane_info)->column_dimension = size_header.col_dimension;
/* read in plane */
data_pointer = (unsigned char *) (*plane)->plane_base;
bytesleft = plsize;
while (bytesleft > 0) {
rbytes = bytesleft;
if (rbytes > BLOCKSIZE) rbytes = BLOCKSIZE;
if (fread(data_pointer,rbytes,1,plfile) != 1) return(-1);
if (need_swap && header.ptype == LLVS_PLF_SHORT)
swap_words(data_pointer,rbytes >> 1);
if (need_swap && (header.ptype == LLVS_PLF_INT ||
header.ptype == LLVS_PLF_FLOAT))
swap_longs(data_pointer,rbytes >> 2);
if (need_cvt_float && header.ptype == LLVS_PLF_FLOAT)
cvt_floats(data_pointer,rbytes >> 2,header.floatfmt,LLVS_NATIVE_FLOATFMT);
data_pointer += rbytes;
bytesleft -= rbytes;
}
/* close file */
fclose(plfile);
return(header.multi_plane_flag);
}
#ifdef DECSTATION
read_plane_vms_var(plane,plane_info,associations,plfile)
PLANE **plane;
PLANE_INFO **plane_info;
char **associations;
FILE *plfile;
{
/* plane file header record structure */
static LLVS_PLANE_FILE_HEADER header;
/* plane size header record structure */
static LLVS_PLANE_SIZE_HEADER size_header;
static unsigned short int rsize;
int plsize; /* # bytes in plane */
llvs_ubyte *data_pointer; /* pointer to data buffer */
int rbytes, bytesleft; /* I/O byte counters */
int need_swap, need_cvt_float; /* flags to indicate if conversions needed */
/* read header record */
if (fread(&rsize,2,1,plfile) != 1) return(-1);
if (fread(&header,32,1,plfile) != 1) return(-1);
need_swap = header.bsex != LLVS_NATIVE_BYTE_SEX;
need_cvt_float = header.floatfmt != LLVS_NATIVE_FLOATFMT;
if (need_swap) swap_longs(&header.pl_level,7);
if (header.ptype == LLVS_PLF_FLOAT && need_cvt_float)
cvt_floats(&header.background,1,header.floatfmt,LLVS_NATIVE_FLOATFMT);
/* computer plane size */
plsize = header.data_length - 12;
/* allocate plane info struct */
*plane_info = (PLANE_INFO *) malloc(sizeof(PLANE_INFO));
if (*plane_info == NULL) return(-1);
/* fill in plane info slots */
(*plane_info)->datatype = header.ptype;
(*plane_info)->level = header.pl_level;
(*plane_info)->row_location = header.row_location;
(*plane_info)->column_location = header.col_location;
(*plane_info)->background.fixnum = header.background.iback;
/* allocate plane it self */
*plane = (PLANE *) malloc(plsize);
if (*plane == NULL) return(-1);
/* allocate space for association list */
*associations = calloc(header.alist_length+1,sizeof(char));
if (*associations == NULL) return(-1);
/* read in association list */
data_pointer = (llvs_ubyte *) *associations; /* start of buffer */
bytesleft = header.alist_length; /* number of bytes to read */
while (bytesleft > 0) {
rbytes = bytesleft;
if (rbytes > BLOCKSIZE) rbytes = BLOCKSIZE;
if (fread(&rsize,2,1,plfile) != 1) return(-1);
if (fread(data_pointer,rbytes,1,plfile) != 1) return(-1);
data_pointer += rbytes;
bytesleft -= rbytes;
}
/* gobble extra byte */
if ((header.alist_length & 01) == 1) fread(&rsize,1,1,plfile);
/* read size header */
if (fread(&rsize,2,1,plfile) != 1) return(-1);
if (fread(&size_header,12,1,plfile) != 1) return(-1);
if (need_swap) swap_longs(&size_header,3);
/* fill in addition slots in plane info */
(*plane_info)->row_dimension = size_header.row_dimension;
(*plane_info)->column_dimension = size_header.col_dimension;
/* read in plane */
data_pointer = (unsigned char *) (*plane)->plane_base;
bytesleft = plsize;
while (bytesleft > 0) {
rbytes = bytesleft;
if (rbytes > BLOCKSIZE) rbytes = BLOCKSIZE;
if (fread(&rsize,2,1,plfile) != 1) return(-1);
if (fread(data_pointer,rbytes,1,plfile) != 1) return(-1);
if (need_swap && header.ptype == LLVS_PLF_SHORT)
swap_words(data_pointer,rbytes >> 1);
if (need_swap && (header.ptype == LLVS_PLF_INT ||
header.ptype == LLVS_PLF_FLOAT))
swap_longs(data_pointer,rbytes >> 2);
if (need_cvt_float && header.ptype == LLVS_PLF_FLOAT)
cvt_floats(data_pointer,rbytes >> 2,header.floatfmt,LLVS_NATIVE_FLOATFMT);
data_pointer += rbytes;
bytesleft -= rbytes;
}
/* close file */
fclose(plfile);
return(header.multi_plane_flag);
}
/*
* write_plane(plane,plane_info,associations,filename) - write out a plane.
*/
#endif
/*
* write_plane(plane,plane_info,associations,filename) - write out a plane.
*/
write_plane(plane,plane_info,associations,filename)
PLANE *plane;
PLANE_INFO *plane_info;
char *associations;
char *filename;
{
static LLVS_PLANE_FILE_HEADER header;
/* plane size header record structure */
static LLVS_PLANE_SIZE_HEADER size_header;
int plsize; /* # bytes in plane */
FILE *plfile; /* plane file */
unsigned char *data_pointer; /* pointer to data buffer */
int rbytes, bytesleft; /* I/O byte counters */
/* open file. abort if open failure */
#ifdef VMS
plfile = fopen(filename,"w", "rfm=var");
#else
plfile = fopen(filename,"w");
#endif
if (plfile == NULL) return(-1);
/* fill in plane file header record */
header.ptype = plane_info->datatype;
header.bsex = LLVS_NATIVE_BYTE_SEX;
header.floatfmt = LLVS_NATIVE_FLOATFMT;
header.reserved = 0;
header.pl_level = plane_info->level;
header.row_location = plane_info->row_location;
header.col_location = plane_info->column_location;
header.background.iback = plane_info->background.fixnum;
header.data_length = plane_size(plane_info) + 12;
if (associations == NULL) associations = "NIL";
header.alist_length = strlen(associations);
header.multi_plane_flag = 0;
/* write header record */
if (fwrite(&header,32,1,plfile) != 1) return(-1);
/* compute plane size (for use later) */
plsize = header.data_length - 12;
/* get pointer to associaions list */
data_pointer = (llvs_ubyte *) associations;
/* and length */
bytesleft = header.alist_length;
/* write out associations list */
while (bytesleft > 0) {
rbytes = bytesleft;
if (rbytes > BLOCKSIZE) rbytes = BLOCKSIZE;
if (fwrite(data_pointer,rbytes,1,plfile) != 1) return(-1);
data_pointer += rbytes;
bytesleft -= rbytes;
}
/* fill in size header */
size_header.datatype_again = header.ptype;
size_header.row_dimension = plane_info->row_dimension;
size_header.col_dimension = plane_info->column_dimension;
/* write out size header */
if (fwrite(&size_header,12,1,plfile) != 1) return(-1);
/* get pointer & size of plane data */
data_pointer = (unsigned char *) plane->plane_base;
bytesleft = plsize;
/* write plane data */
while (bytesleft > 0) {
rbytes = bytesleft;
if (rbytes > BLOCKSIZE) rbytes = BLOCKSIZE;
if (fwrite(data_pointer,rbytes,1,plfile) != 1) return(-1);
data_pointer += rbytes;
bytesleft -= rbytes;
}
/* close file */
fclose(plfile);
return(0);
}
/* compute plane size from plane info */
plane_size(plinfo)
PLANE_INFO *plinfo;
{
int elements; /* element count */
elements = plinfo->row_dimension * plinfo->column_dimension;
switch (plinfo->datatype) {
case LLVS_BIT: return( (elements + 7) / 8);
case LLVS_BYTE:
return( elements * sizeof(unsigned char));
case LLVS_SHORT:
return( elements * sizeof(short int));
case LLVS_INT:
return( elements * sizeof(long int));
case LLVS_FLOAT:
return( elements * sizeof(float));
}
}
swap_longs(array,element_count)
llvs_integer array[];
int element_count;
{
union {
llvs_ubyte bytes[4];
llvs_integer longword;
} a,b;
register int i;
for (i = 0; i < element_count; i++) {
a.longword = array[i];
b.bytes[0] = a.bytes[3];
b.bytes[1] = a.bytes[2];
b.bytes[2] = a.bytes[1];
b.bytes[3] = a.bytes[0];
array[i] = b.longword;
}
}
swap_words(array,element_count)
llvs_half_integer array[];
int element_count;
{
union {
llvs_ubyte bytes[2];
llvs_half_integer word;
} a,b;
register int i;
for (i = 0; i < element_count; i++) {
a.word = array[i];
b.bytes[0] = a.bytes[1];
b.bytes[1] = a.bytes[0];
array[i] = b.word;
}
}
cvt_floats(array,element_count,current_format,desired_format)
llvs_integer array[];
int element_count,desired_format;
{
static llvs_integer old,new;
register int i;
void vax_to_ieee(), ieee_to_vax();
for (i = 0; i < element_count; i++) {
old = array[i];
new = 0;
/*
if (LLVS_NATIVE_BYTE_SEX == LLVS_LOW_BYTE_FIRST &&
current_format == LLVS_IEEE_SINGLE_FLOAT) swap_longs(&old,1);
*/
switch (current_format) {
case LLVS_DEC_SINGLE_FLOAT:
switch (desired_format) {
case LLVS_DEC_SINGLE_FLOAT: new = old; break;
case LLVS_IEEE_SINGLE_FLOAT: vax_to_ieee(&old,&new); break;
}
break;
case LLVS_IEEE_SINGLE_FLOAT:
switch (desired_format) {
case LLVS_DEC_SINGLE_FLOAT: ieee_to_vax(&old,&new); break;
case LLVS_IEEE_SINGLE_FLOAT: new = old; break;
}
break;
}
if (LLVS_NATIVE_BYTE_SEX == LLVS_LOW_BYTE_FIRST &&
desired_format == LLVS_IEEE_SINGLE_FLOAT) swap_longs(&new,1);
array[i] = new;
}
}
/*****************************************************************
fjm -- 11/6/87 -- Function IEEE_VAX_S(Value)
This function takes an IEEE format MC68881 Single precision floating
point number and returns the VAX F_floating form of the number if it
is in range.
Note: The smallest vax floating point number is 4 times smaller than
the smallest ieee floating point number in normallized form.
The largest vax floating point number is .5 times as large as
the largest ieee floating point number.
Actual ranges:
Vax IEEE
--- ----
max 1.7014119x10**38 3.4028243x10**38
min 0.29387365x10**-38 1.175495x10**-38 (normalized)
1.4013x10**-45 (de-normalized)
Let E = the exponent part of the real (in signed magnitude form), and
let M = the mantisa, and S = the sign.
The vax represents floating point numbers as:
S bit -- bit 15
E -- bits 7-14, 8 bit, excess 128 exponent.
M -- bits 6(MSB)-0 and bits 31-16(LSB) unsigned fraction.
Numbers are stored in a normalized form with a hidden 1 bit
representing a 0.1 is immediately to the left of the MSB of M. Note
that the radix point of the fraction is to the left of the hidden
bit in this form.
IF E .ge. 1 then
value = (-1)**S x 2**(E-128) x 0.1M
IF S .eq. 0 .and. E .eq. 0 then
value = 0 (unsigned)
IF S .eq. 1 .and. E .eq. 0 then
illegal value, signalled on attempted operation.
The IEEE representation is as follows:
S bit -- bit 31
E -- bits 23-30, 8 bit, excess 127 binary exponent.
M -- bits 22(MSB) - 0(LSB) unsigned fraction.
Numbers are stored in either normalized or de-normalized form. In
normalized form (the usual representation) a hidden 1 bit representing
a 1.0 is immediatly to the left of the MSB of M. In denormalized form,
the hidden bit is 0. See below. Note that in IEEE form, the radix point
of the fraction is to the right of the hidden bit.
IF E .ge. 1 .and. E .le. 254 then
actual value = (-1)**S x 2**(E-127) x 1.M
IF E .eq. 0 .and. M .eq. 0 then
value = signed zero (S bit is preserved)
IF E .eq. 255 .and. M .ne. 0 then
not a number (NAN). M can have any bit pattern, and the
result of any operation on a NAN with the MSB of F set
on an IEEE implementation results in a signal. The
interpretation on any value associated with a NAN is left
to the application.
IF E .eq. 255 .and. M .eq. 0 then
value = Plus or minus infinity, depending on S.
IF E .eq. 0 .and. M .ne. 0 then
denormalized number, used to represent numbers less
than can be represented in normalized form. The hidden bit
is assumed to a zero.
value = (-1)**S x 2**(E-126) x 0.M
Note that the vax and ieee forms differ by a bias of 1 in their stored
exponent form, and that they also differ implicitly by a power of 2 due to
the difference in normalization scalling (ieee = 1.M, vax = 0.1M).
Thus the conversion for the exponent is Evax = Eieee + 2. Further, the vax
can represent smaller numbers in normallized form than can the 68881, so
this routine converts the de-normalized numbers that are representable
on the vax. Thus, all ieee normalized numbers with exponents less than 254
are convertable to vax representations. Further, Some of the de-normalized
numbers are convertable. Loss of range (overflow) occurs on the high end.
The actual conversion outline follows:
Normallized numbers:
numbers in the magnitude of:
1.175495 x 10**-38 to 1.7014119 x 10**38
are converted exactly, with no loss of precision.
numbers with a magnitude greater than 1.7014119 x 10**38
are converted to a vax reserved operand with sign of 1 and
exponent and mantissa of zero. This is the equivalent of
the result of a floating overflow on a 780 class machine.
De-normalized numbers:
numbers in the magnitude of:
0.29387365 x 10**-38 to 1.175494 x 10**-38
are converted. Note that while the conversion is exact,
the vax has 1 to 2 bits more precision in this range than is
represenatble in the ieee form. The extra 1 or 2 bits are assigned
zeros in the conversion.
numbers less than 0.29387365 x10**-38 are mapped on to vax zero
with S=0, E=0, and M=0.
Zeros:
both positive and minus zero in the ieee implementation are
mapped on to vax zero with S=0, M=0, and E=0.
Infinities:
Infinities have no dual in the vax architecture, as such, the
value mapped is a vax reserved operand, with S=1, E=0, and M=0.
This is the equivalent of a floating overflow result on the
780 class machines.
Not Numbers (NAN's):
These are mapped onto vax operands by setting the sign bit,
clearing the exponent, and preserving the mantissa. Note that
this conversion losses the original sign bit. The ieee representation
has twice as many NAN's as the vax, so half are lost.
integer*4 function IEEE_VAX_S(value) ! really of type bit vector.
implicit none
integer*4 value
integer*4 S
integer*4 E
integer*4 M
Fetch the fields from IEEE format:
31 30 23 22 0
+--+--------------+------------------------------+
| S| Exponent |MSB Mantissa LSB|
+--+--------------+------------------------------+
S = lib$extzv(31,1,value)
E = lib$extzv(23,8,value)
M = lib$extzv(0,23,value)
Note: The following code is optimized to deal with the two most likely
casses first: namely, normal values and zeros.
Zeros and de-normalized numbers:
if ( E .eq. 0 ) then
Zeros:
if( M .eq. 0 ) then
S = 0
de-normalized number:
else ! M .ne. 0
number is representable if bit 21 or 22 is set.
shift the mantisa the right number of bits and strip the
high order set bit which becomes the hidden bit on the vax.
Numbers outside the representable range are set to zero.
if ( ( M .and. '400000'x) .ne. 0 ) then
M = (M .or. '3FFFFF'x) * 2
E = 2
else if ( ( M .and. '200000'x) .ne. 0 ) then
M = (M .or. '1FFFFF'x) * 4
E = 1
else
S = 0
E = 0
M = 0
end if
end if
Normal value:
else if ( E .lt. 254 ) then
E = E + 2
un-representable (overflow)
else if ( E .eq. 254 ) then
S = 1
E = 0
M = 0
Infinities and NAN's
else ! E .eq. 255
S = 1
E = 0
end if
Store the numbers in vax format.
31 16 15 14 7 6 0
+-----------------------+--+----------+-------------+
| Mantissa LSB| S| Exponent |MSB Mantissa |
+-----------------------+--+----------+-------------+
call lib$insv(S,15,1,ieee_vax_s)
call lib$insv(E, 7,8,ieee_vax_s)
call lib$insv(lib$extzv(16,7,M),0,7,ieee_vax_s)
call lib$insv(lib$extzv(0,16,M),16,16,ieee_vax_s)
return
end
Frank J. Manion
The Fox Chase Cancer Center
Phone: (215) 728-3660 7701 Burholme Avenue
Philadelphia, PA 19111
USA
*******************************************************************/
void ieee_to_vax(ip,cp)
int *ip;
unsigned char *cp;
{
int s, e, m;
unsigned int i;
/* Fetch the fields from IEEE format:
31 30 23 22 0
+--+--------------+------------------------------+
| S| Exponent |MSB Mantissa LSB|
+--+--------------+------------------------------+
*/
i = *ip;
#if LLVS_NATIVE_BYTE_SEX == LLVS_LOW_BYTE_FIRST
swap_longs(cp,1);
#endif
s = 1 & (i >> 31);
e = 0x0ff & (i >> 23);
m = 0x7fffff & i;
/*
Note: The following code is optimized to deal with the two most likely
casses first: namely, normal values and zeros.
*/
if (e == 0) { /* Zeros and de-normalized numbers: */
if (m == 0) s = 0;
else {
/*
number is representable if bit 21 or 22 is set.
shift the mantisa the right number of bits and strip the
high order set bit which becomes the hidden bit on the vax.
Numbers outside the representable range are set to zero.
*/
if (m & 0x400000) {
m = (m | 0x3FFFFF) << 1;
e = 2;
}
else if (m & 0x200000) {
m = (m | 0x1FFFFF) << 2;
e = 1;
}
else {
s = 0;
e = 0;
m = 0;
}
}
}
else if (e < 254) e += 2; /* Normal value: */
else if (e == 254) { /* un-representable (overflow) */
s = 1;
e = 0;
m = 0;
}
else { /* E .eq. 255 - Infinities and NAN's */
s = 1;
e = 0;
}
/*
Store the numbers in vax format.
31 16 15 14 7 6 0
+-----------------------+--+----------+-------------+
| Mantissa LSB| S| Exponent |MSB Mantissa |
+-----------------------+--+----------+-------------+
*/
*cp++ = (m >> 16) | ((1 & e) << 7);
*cp++ = (s << 7) | (e >> 1);
*cp++ = 0xff & m;
*cp++ = 0xff & (m >> 8);
}
void vax_to_ieee(cp,ip)
unsigned char *cp;
unsigned int *ip;
{
int s, e, m;
unsigned int i;
/* Fetch the fields from VAX format:
31 16 15 14 7 6 0
+-----------------------+--+----------+-------------+
| Mantissa LSB| S| Exponent |MSB Mantissa |
+-----------------------+--+----------+-------------+
*/
#if LLVS_NATIVE_BYTE_SEX == LLVS_HIGH_BYTE_FIRST
swap_longs(cp,1);
#endif
s = *(cp + 1) >> 7;
e = ((0x7f & *(cp + 1)) << 1) | (*(cp + 0) >> 7);
m = ((0x7f & *(cp + 0)) << 16) | (*(cp + 3) << 8) | *(cp + 2);
/*
Note: The following code is optimized to deal with the two most likely
casses first: namely, normal values and zeros.
*/
if (e > 1) e -= 2; /* Normal value: */
else if (e == 0) { /* Zeros and de-normalized numbers: */
if (s == 0) m = 0;
else { /* NAN & Infinity */
m = 0;
e = 255;
}
}
else { /* un-representable (overflow) */
s = 0;
e = 0;
m = 0;
}
/*
Store the numbers in IEEE format.
31 30 23 22 0
+--+--------------+------------------------------+
| S| Exponent |MSB Mantissa LSB|
+--+--------------+------------------------------+
*/
*ip = (s << 31) | (e << 23) | m;
#if LLVS_NATIVE_BYTE_SEX == LLVS_LOW_BYTE_FIRST
swap_longs(ip,1);
#endif
}