Random Generator
Volume Number: 1
Issue Number: 10
Column Tag: Fortran's World
"Random Generator shows off MacFortran
By Mark McBride, Assit. Professor of Economics, Miami University,
Oxford, Ohio
Having used the Macintosh for over a year in my routine daily work of word
processing and telecommunicating and for some minimal programming in Pascal and
assembly, I decided it was time to consider expanding the activities I do on the Mac.
Being an economist, most of my computer work focuses on complex statistical analysis
on the mainframe computers using SAS, SPSS, and Shazam, as well as custom Fortran
programs. Therefore, I began investigating ways to convert the custom mainframe
Fortran programs to the Mac.
This column will cover three topics of interest to Mac users wanting to program
in Fortran or convert Fortran porgrams from other machines. First, tutorials on how
to implement Mac features from within Fortran programs. Second, strategies for
converting Fortran programs to the Mac. And third, combining the first two, creating
custom Mac versions of your mainframe programs which take maximum advantage of
the Mac's user interface with the least amount of conversion effort.
Which Fortran?
In beginning my quest, I laid down four criteria for the conversion of Fortran
programs to the Mac. First, I should be able to easily import the source code from the
mainframe via the modem. Second, I should be able to compile and run the existing
code on the Mac with a minimum of conversion problems. Third, I should be able to
redesign parts of the code to have Mac-like features, as I deemed necessary. And
finally, I should be able to create self-contained applications.
MacFortran by Absoft
In evaluating Fortran systems to meet these criteria, I discovered that only
MacFortran by Absoft appeared to meet all four criteria. The Absoft system (version
2.0a; version 2.1 is due for release this month) consists of Apple's Edit program (a
general purpose text editor used in the MDS and Consulair C systems), a Fortran 77
compiler, a linker, an interactive debugger, and a library manager. Only the linker
appears to have some deficiencies (more on that below). MacFortran compiles into
68000 machine code. The compiler has many options, including an option for
compiling Fortran 66 source code. Probably one of the most interesting features of the
compiler is the ability to generate 68000 assembly source code which can be used
with an assembler to fine tune the code. (This is also useful for studying how
compilers produce native code.) MacFortran's desirable language features include
structured programming constructs: if then else, block if, case, etc. The interactive
debugger is almost as easy to use and as powerful as the debugger in MacPascal. This
makes debugging relatively easy in MacFortran. While the documentation is thin in
places, the system is fairly easy to get up and running and access to the toolbox is well
documented. (Version 2.1 has an extra 100 pages of toolbox docs included.)
Fig. 1 Screen output of this month's Fortran program
Using MacFortran
MacFortran requires two drives to use it effectively. I keep Edit, the compiler,
the debugger, and the MacFortran overlay files on the internal drive along with a
stripped down Mac system file and an Imagewriter file. This leaves about 35k of free
space. I have removed the MacFortran overlay file -- f77003.fc-- from my work
disk. This overlay file is necessary only if you are going to generate assembly source
code during compiles. In the external drive, I keep commonly used subroutine code
files, source files, the linker, and the library manager. The external disk does not
contain any Mac system files. This arrangement seems to provide a workable
environment for developing programs. (Don't you agree the Mac should have had the
800K drives it was designed for? -Ed)
Converting a Fortran Program
For a first attempt at converting programs, I choose a relatively simple Fortran
source code: an economic simulation of a small third world country (Fredonia)
developed by a colleague. The Fredonia simulation is about 1500 lines of code which is
essentially a large DO LOOP over straight line code. Only 3 short subroutines exist
within the source code. MacTerminal provided easy downloading of the code from the
HP 3000 minicomputer via text capture. The Edit program read the MacTerminal file,
allowing me to remove all the extraneous information from the download.
Before compiling the source code, I checked the file I/O conventions used in the
source code against those available under MacFortran. MacFortran handles the file I/O
specifications of Fortran 77. However, there are a few items worth noting. First,
while writing output to the printer via unit 6 is possible, data input with read
statements using unit 5 are not available in MacFortran. Second, the file unit
identifier * is connected to the I/O devices defined by units 5 and 6. The * unit
identifier can be redirected to the keyboard for reads and the screen for writes with a
compiler option. Third, the file unit identifier 9 is connected to the keyboard for reads
and the screen for writes. Fourth, other files read from or written to need to have
their OPEN statements checked against the syntax that MacFortran uses for open
statements. If the mainframe program used JCL statements to assign file I/O, then the
ported program will need OPEN statements added to establish the file preconnections. A
final word of caution concerns writing to the printer via unit 6. MacFortran will
spool your output to a temporary file. This temporary file will be sent to the printer
when your program ends by a subroutine called spool. To avoid out of memory errors
at runtime (error=64), include the following subroutine in your source:
subroutine dum
integer*2 ary(1000)
common ary
return
end
This forces MacFortran to reserve enough memory to load the spool subroutine.
The Fredonia source file compiled with only one error on the first pass. This
error was caused by the absence of a Fortran subprogram specific to the HP 3000
which generates random numbers. The ensuing search for a random number generator
allowed me to explore some of the intricacies of the MacFortran system.
Implementing Random Numbers
A search of the MacFortran manual revealed that access to the toolbox included
the random number toolbox routine which is part of Quickdraw (see Inside Mac for a
description of random). The toolbox random routine can be seeded in a system global
variable, RndSeed, in order to generate different random sequences. When Quickdraw
is initialized, Rndseed is set to zero.
Given that the location of RndSeed is known via an offset to a pointer contained in
register A5, direct access to the seed location from Fortran was not possible. This is
because the present system does not support access to the quickdraw globals. However,
Absoft states version 2.1 includes access to system global variables, as well as RAM
based packages, which are not currently supported. I decided to write a short assembly
language routine to seed the random number generator.
This turns out to be more difficult than it sounds. Apparently MacFortran also
uses the A5 register internally, forcing Absoft to relocate the Mac pointer contained in
A5 that assembly programmers have learned to love. Absoft states that the Mac pointer
is located at -4(A0), but I still haven't gotten the assembly based seeding to work yet.
This is not to be critical of Absoft, who have been extremely patient and helpful in
answering the duffer questions of a neophyte assembly programmer. I decided to wait
on version 2.1 to access globals directly from Fortran. Others who want to call
external assembly language subprograms would be well advised to contact Absoft to find
the best solution for their particular needs, and in particular, making sure they have
version 2.1. I will report a general solution as soon as I figure/ find it out.
The next solution tried was to implement a random number generator in Fortran.
The routine I selected is given in Rand.for shown in listing 2. This random number
function returns a real value between zero and one. The random sequence can be
reseeded on any call or a fixed sequence can be maintained for program debugging
purposes.
Examination of the random number function source code reveals two interesting
features. One is the use of the Save statement. A subprogram in MacFortran does not
save local variable values between succesive calls of the program. The random number
generator needs to retain local variable values between calls and does so with the Save
statement.
ToolBox Support
Second, I use the Macintosh toolbox traps TickCount and BitXor. MacFortran uses
a general purpose subprogram called toolbx to handle toolbox traps. Toobx is defined
as integer*4 and can be used as either a subroutine call or as a function call.
MacFortran keeps track of which is being done based upon which toolbox routine is
called.
To make a toolbox call in MacFortran the program defines and assigns values to
the necessary variables of information to be passed or received. This information is
passed along with the name of the toolbox routine by a call to the toolbx subprogram
(Note: this is very similiar to the inLine procedure in MacPascal). Absoft has
provided include files that handle the toolbox name and parameter declarations. Absoft
has also provided example source code files and good documentation on accessing the
toolbox from Fortran.
[The way this toolbox calling is implemented is non-standard. A source file called
toolbx.par contains a list of trap names equated to integers from 0 to 500 or so. The
trap name is set equal to this integer index in your program by either including this
file of definitions, or using the parameter statement to assign the integer value to the
trap name. Apparently the subroutine toolbx.sub uses the integer value as an index into
it's own table of glue routines, where it obtains the real trap address and executes the
toolbox call. The source code to toolbx.sub is not provided. Since there is no obvious
connection between the integer values in the file toolbx.par and the trap address, and
since the trap names are not in any kind of order, it is a bit difficult to wade through
the 500 assignments looking for the trap call your interested in. The trap names are
standard so by including the parameter file you don't have to bother trying to figure
out how Absoft happened to assign those integer values to each trap name! -Ed.]
[One problem with the toolbox definitions is that in the toolbx.par file included in
version 2.0, many of the trap calls are unimplemented with a comment saying "...for
future implementation...". We have already mentioned the fact that RAM based packages
and access to the quickdraw globals is missing in this version. We have requested a
copy of version 2.1 to see if the toolbox is more fully implemented, as we expect. We
will report on version 2.1 in the next issue including a review of the toolbx.par file to
see how many trap calls are implemented. -Ed.]
Using the Rand function
Listing 1 provides the source file Random Test.for which checks the accuracy and
speed in using the Tausworthe random number generator. This program does not
create or use any special Mac features, such as windows or menus. The program uses
the default tty like environment Absoft has set up. This environment is useful when
first porting over a Fortran program to ensure that the compiled code is behaving the
same on the Mac as it did the mainframe. We'll talk next time about creating Mac user
interface features in Fortran.
Upon successful compilation, you can immediately run your new codefile by
double clicking the Random Test apl file on the desktop. This will cause the MacFortran
run time library (f77.rl) to be dynamically linked in, as well as the external
subprogram toolbx.sub the first time it is called. This approach of dynamic runtime
linking can be useful if you have a set of commonly used subroutines.
Linking to Stand alone
One of the stated goals at the start of the article was the ability to link the
resulting code into a single stand alone clickable application. This can be done with the
MacFortran linker. To link the example program double click the linker and execute
the following linker commands in response to the > prompt:
>f Random Test
>f toolbx
>l f77.rl
>o Random Program
> (carriage return)
Be sure that the files Random Test apl, toolbx.sub, and f77.rl are all on the same
disk and that the commands are executed in the above order. The primary restriction
is that the runtime library should always be the last file linked. This will generate an
approximately 22k application file (2k from Random Test apl, 3k from toolbx.sub,
and 17k from f77.rl, the fortran run time support module required of any stand alone
program).
While linking a stand alone file in this sample program was easy enough, that is
not always the case with the MacFortran linker. The linker can get lost sometimes and
report no unresolved references, even when some still exist. Notably, this situation