%
% PSI Programmer's Manual
%
% Binary I/O --- libciomr
%
% Daniel Crawford, 1 February 1996
% Updated, June 2000
%
For completeness and reference, the old PSI I/O system, libciomr, is
described here.

A binary file is identified by the \PSIthree\ module through a unit
number and not by a complete name, just as in the Fortran programming
language.  The module does not generally have access to the full name
of the physical file(s) which make up the unit --- only the low-level
I/O functions require this information.  For example, let's say the
programmer wishes to open binary file number 92 (the supermatrix file
constructed by \PSIcscf) and read data from it.  After initialization
of the input parsing system (see sections \ref{C_IP} and
\ref{C_Program}), he or she would call the \celem{rfile()} routine.
This function requires only the unit number of the file as an argument
--- in this case, 92.  This unit number is passed to a lower-level
routine, \celem{ioopen{\_}()}, which determines the I/O method
available.\footnote{At present, the only method available is
sequential I/O, though the originial authors of the I/O routines left
open the possibility of other, more unusual I/O techniques, including
RAM disks and asynchronous access.}  Then, the appropriate
file-opening routine is called.  This routine
(e.g. \celem{sequential{\_}ioopen()}) determines the number of volumes
(i.e. the number of physical files) across which the binary file will
be partitioned.  It then constructs the name of each physical file
based on the information provided by the user input (or, if no input
is available, a default name), and finally opens each physical file.
All of the steps beyond the call to \celem{rfile()} are conveniently
hidden from the programmer.  After the module is finished with its
interaction with the unit, the file is closed using \celem{rclose()},
which will delete the file if the programmer wishes.

There are two primary functions in \celem{libciomr.a} which allow the
PSI C modules to interact with binary files.  These are
\celem{wreadw()} and \celem{wwritw()}.  Both of these routines require
as arguments the unit number, a data buffer, the number of bytes to be
read or written, and the starting byte address in the file.  In
addition, both provide (as an argument, not a return value) the ending
bytewise file pointer after the read/write has completed.  (See
\file{libciomr/libciomr.h} for the exact syntax for calling these two
routines.)  For example, if the programmer wishes to read 512 double
precision floating point words from \FILE{92}, starting at byte number
13, into the array \celem{arr}, the appropriate call to
\celem{wreadw()} would be
\begin{verbatim}
        wreadw(92, (char *) arr, 512*sizeof(double), 13, &next_byte);
\end{verbatim}
The cast, \celem{(char *)}, is necessary so that the data in \FILE{92}
can be loaded into arrays of different types, e.g.~integer or double
precision floating point words.  Note also that a pointer to
\celem{next{\_}byte} must be passed so that the ending bytewise file
pointer will be returned.  A similar call is used for
\celem{wwritw()}.  The read/write requests are carried out by the
low-level I/O routines, which pass the data to or from the physical
files in blocks of 8192 bytes (this value may be changed by user
input).  This can significantly reduce the amount of time spent by the
CPU waiting to send or receive data to or from the physical devices.

There are four other routines which are sometimes used for reading and
writing data in binary files: \celem{sread()}, \celem{swrit()},
\celem{rread()}, and \celem{rwrit()}.  These functions work similarly
to \celem{wreadw()} and \celem{wwritw()}, but do not require bytewise
file addresses as arguments.  Instead, the global file pointer is
maintained by the I/O routines themselves, and read/write requests
automatically begin at the boundaries of so-called {\em sectors},
which are here defined to be blocks of 1024 4-byte integer words.  The
routines are frequently used by older PSI Fortran modules, which were
written before computer operating systems automatically buffered disk
I/O in memory.  However, modern workstations have made these functions
mostly obsolete, and we recommend using them only for interaction with
files constructed by older modules.
