Jonathan Slaton, probably one of the world's youngest
Fortran programmers, tell us why he likes to use F_World.
An Appreciation of F
John Reid, co-author of The F Programming Language,
gives an overview of F, emphasizing differences between
F and Fortran 90/95.
Michel Olagnon runs some benchmarks and concludes
that you don't loose performance by sticking to the constructs
provided in F.
Little Giants--The New Fortran Subset
Loren Meissner compares F with the other Fortran subset--ELF
from Lahey Computer Systems.
Personal Observations Teaching with F
Ralph Jay Frisbie, one of the first to use F in the classroom,
shares his experiences and suggestions.
Across the Editor's Desk
Sample F Programs
American La Roche International AMOCO Production ARAMCO Army Research APG Site ASC School Systems Babcok and Wilcox Bettis Atomic Power Laboratory Boeing Brookhaven National Laboratory Bull MTS Centre Interuniversitaire de Calcul Christian Michelsen Research Comalco Research Centern Cray Research France Cray Research Japan Cray Research UK David Taylor Research Center Defence Research Agency Delft University of Technology Department of Transportation Edinburgh Portable Compilers Fermilab Fujitsu Geophysical Fluids Dynamics Laboratory GMD - Berlin Hamilton Standard Division Hellenic Military Geographical Service Hewlett-Packard Hitachi Institut Laue Longevin Jet Propulsion Laboratory Karl Kamloth Lawrence Livermore Laboratory Lincoln Laboratory MIT Los Alamos National Laboratory MATRA Defense Microsoft Mitsubishi Mobil Research & Development NASA Ames Research Center NASA Langley Research Center National Center for Atmospheric Research Numerical Algorithms Group ONERA Orbital Engine Company PUC-Minas Salford Software Marketing Sandia National Laboratories Schlumberger Scientific Services Shell Development Siemans Research SLAC Teknillen Korkeakoulu University of Liverpool University of Western Ontario U.S. Geological Survey Visual Numerics Westland Helicopters
Reach out and touch the Fortran community. This special and knowledgeable audience wants to know about your products and services. Please call Chuck Ritz at +1-714-441-2022 to sponsor articles or issues of forthcoming electronic issues of the Fortran Journal.
The editors of the Fortran Journal are Walt Brainerd and Charles Ritz.
Copyright © 1996 Unicomp, Inc. All rights reserved.
This material may be reproduced for individual use;
commercial use of the material requires the prior
permission from Unicomp, Inc.
The Fortran Journal is a registered trademark of Unicomp, Inc.
As announced in the previous issue, the Fortran Journal henceforth will be published exclusively in electronic form, using the World Wide Web site of the Unicomp Fortran Market.
It is perhaps auspicious that the Fortran Journal is making this significant change just as the F programming language is featured on its pages. The Fortran Journal will be presented using a more modern medium, the internet; the F programming language provides a more modern programming language for scientific and engineering computing.
As electronic media provide a way to disseminate information to many more readers and lower cost, the F programming language provides much more effective programming tools at lower cost and may well provide the only hope for keeping Fortran as the language of choice for numerical computing.
Fortran has always been the most effective programming language for scientific computing. It is designed to allow efficient implementations on a wide variety of computing devices, from PCs to supercomputers. With the advent of Fortran 90, the language also embraces modern software engineering concepts, such as structured programming and data encapsulation. And, if you use the features, the language provides the tools to create robust programs with many of the older common errors detected by the compiler.
The problem is that the language just keeps getting bigger and bigger. It is, of course, essential to be able to keep running old programs that work. This means that Fortran must not only retain all of the old standard features, but most of the things thought up by vendors and users that seemed like good ideas at the time (and, for the most part, were good ideas). There is a large cost to convert programs; there is also a large cost to retain all of the old features of Fortran in future compilers. Each new feature that is introduced must interact correctly with all of the old features. This makes compilers difficult to build and hence expensive. Users pay for this in higher software costs.
In addition to the problem of "legacy code", there is the problem of "legacy programmers". Many (most?) Fortran programmers are not "computer scientists", but other kinds of scientists who use the computer as a tool to solve their kind of science or engineering problems. It is painful and inefficient for them to learn a whole new programming language.
So how does the F programming language help with these problems? It is a clean, modern, subset of Fortran 90. Programmers familiar with Fortran 90 have nothing to learn except which features of Fortran 90 are in F. Even those familiar only with Fortran 77 have only to learn the parts of Fortran 90 that have been incorporated into F. This addresses the "legacy programmer" problem.
Students should not have to learn to deal with outmoded ways of programming (at least not until they have to deal with old programs), and the educational version of F has just those features that students should be learning.
To handle the "legacy program" problem, the professional version of F allows calls to nonF procedures, such as those written in Fortran 77, Fortran 90, or C. New codes and parts of older programs that are revised can be written in F.
Since most readers of the Fortran Journal are familiar with Fortran 90, the first article describes the things in Fortran 90 that are not in F, with some explanation of why choices were made. This article is written by John Reid, co-author with Mike Metcalf of Fortran 90/95 Explained and their new book The F Programming Language.
Michel Olagnon has done an important experiment to show that you will not suffer serious performance penalties by using the features of Fortran 90 that are in F. His article provides some details about this experiment.
Loren Meissner compares and discusses F and the other proposed Fortran subset, ELF90 from Lahey Computer Systems, providing a critical assessment of the content of the two subsets.
Ralph Frisbie is one of the first to use F in a college programming course and reports on his experiences.
However, we begin with what is perhaps the most significant article of all, the recorded reactions of an eight-year-old who was one of the first users of F in the point-and-click environment available on Windows.
F is available on a wide variety of platforms: Windows 95,
several Unix workstations, and Linux (free). There are
highly optimized versions for Solaris 1 and 2 made possible
by using the Fujitsu Fortran 90 optimizing compilation technology.
Check out the possibilities at:
Editor's note: While testing F_World, the point-and-click learning environment available with F on Windows, it was beta tested it on potential programmers of all ages. Here is the reaction of the youngest graduate of F_World.
I like F_World. It's kind of hard. But in some ways it was easy. F_World is pretty cool. There are 34 steps. I've done F_World 2 times. F_World is on a computer. My 2 favorite names are: MyWeirdModule and JonathansFirstSubroutine. (You have to give them names.) I've made it add, subtract, and multiply. (You can't make it divide.) When you do it you make a computer program. They have beginner, intermediate, and advanced. (You are a beginner and so am I!) Last time I did it with my Uncle. He made it say "Jonathan is a booger". I made it say "Brooks is a dummy!"
About the Author
Jonathan Slaton, age 8, is a second grade student at Rockcreek
Elementary School, Columbus, Indiana.
Rutherford Appleton Laboratory
F is a subset of Fortran 90, chosen by Walt Brainerd, David Epstein, and Dick Hendrickson of Imagine1, Inc. to be easy to learn, easy to implement, easy to understand, and safe. At the same time, it is powerful enough for use in large programs; indeed it is far more powerful than Fortran 77.
The three originators invited Mike Metcalf and me to write an F version of our Fortran 90 book. When we began, the design of F was not quite finalized, which allowed me to have a small hand in that finalization. Our book has been available since the early summer, and gives a complete description of the language. It also contains an appendix that lists the differences from Fortran 90.
The aim of this article is to give the reader with some knowledge of Fortran 90 an appreciation of the omissions, both of what they are and the reasons. It does not give the reader a full appreciation of F as a language in its own right. For that, you need to buy our book. This article does, however, provide a quick appreciation of what is left in its concluding section.
Where Fortran 90 has alternative syntax for expressing the same thing, F usually picks a good one and discards the rest. For example, all type declaration statements must have a double colon and must specify all the attributes of the entities. The statements allocatable, dimension, intent, optional, parameter, pointer, save, and target are therefore all discarded.
This represents a completely different approach from that adopted by X3J3 during the development of Fortran 90. There, backwards compatibility had to be assured and it was felt that users of the language should have a choice, as long as the burden on implementors was not too severe.
The problem with these choices is that each programmer develops a personal style and actually uses a different language subset. It means that reading a program written by someone else is harder; portability between people has suffered. It also makes it harder to develop automated tools to maintain large codes.
Other cases where only one alternative is available in F are listed in Section 19.
Restrictions on the source form are designed to make it easier to catch all occurrences of a name with a tool or a case-sensitive editor. All keywords must be in lower case and any use of upper case in names must be consistent. For example, the variable John cannot be referenced as john. No name is permitted to terminate with an underscore. No token may be continued from one line to another, even when an embedded blank is permitted, such as in end if. This means that there is no need for a continuation line ever to begin with &, so this is not permitted.
F does not have the include statement because of its non-portability. Also, it does not allow ; statement separators.
F contains none of the obsolescent features of Fortran 90 nor those designated for Fortran 95. Since all have replacements within Fortran 90, this is very much in accord with the aim of avoiding duplications. The obsolescent features of Fortran 95 are
Labels are regarded as undesirable because they allow "spaghetti coding", that is, coding where the flow of control is very complicated and hard to follow. Even the most disciplined use of labels leaves the reader uncertain over how each labeled statement may be reached. For example, consider
if (a > b) then : if (c == 0) then : if (disaster) go to 10 : end if end if 10 if (disaster) then : end if
where the intention is simply to leave the nested if construct when disaster strikes. Without doing some work, the reader cannot be sure that the labeled statement cannot be reached in other ways.
F permits no use of labels. There is therefore no go to statement. Also, the continue statement is redundant so is excluded. For I/O, the format statement and specifiers such as end= disappear, but all have obvious alternatives so omitting them also accords with the aim of avoiding duplications. Similarly, the labeled do statement is excluded.
The total removal of labels is an aspect of the language for which I have reservations. There are a few situations when its disciplined use yields the simplest and clearest code. This is illustrated with the nested if construct above. There are times when we need to exit directly from nested constructs.
For the sake of safety, F requires all typed entities to be explicitly declared. Strictly speaking, this means that implicit none is redundant and originally F excluded this statement. However, it has been restored because of its importance when a program is presented to a Fortran 90 compiler and possibly later altered. A consequence is that F programs can be written that are also Elf90 programs.
Some further rules on declaring attributes explicitly are made for the sake of clarity and safety. Each object with an initial value must be given the save or parameter attribute. All procedures and generic specifiers defined in a module must appear in a public or private statement there. This means that default accessibility is used only for entities accessed from a module; therefore, a module with no use statements is not permitted to have a default accessibility statement.
The use of an explicit kind value, for example, in the constant 1.0_4 is nonportable since kind values vary from system to system. Therefore, F requires each kind specification to employ a named constant, in the expectation that it has been given a value in a portable way such as
integer, parameter :: & short = selected_int_kind(4)
This rule also applies to each kind value in an intrinsic procedure reference.
F does not support nondefault kinds of characters so no character entity may be specified with a kind parameter.
To simplify the interpretation of real and complex literal constants, F requires each real literal constant to have a decimal point preceded and followed by a digit string and not to have d as its exponent letter. The parts of a complex literal constant must be real and have the same kind with the same named constant. If a kind type parameter value is explicitly specified for one part, it must be specified for both and with the same named constant.
To avoid complications in tools, F does not permit apostrophes as character string delimiters.
F does not permit a character constant to be qualified by a substring. This prohibits bizarre cases such as
which is not really a constant since its value varies with i and yet is not a variable either since it is not permitted on the left of an assignment statement.
The syntax of the data statement is outmoded and unsafe, so this statement is excluded from F. An unfortunate consequence is that F does not permit integer constants to be specified in binary, octal, or hexadecimal notation.
Main program variables are not permitted to be given initial values. This is because they provide no useful functionality beyond that available from assignment statements at the start of the main program, since such statements are executed only once. Such assignment statements may also be used if partial initialization of an object is desired (as data statements are disallowed).
F eliminates the following as redundant: allowing a comma after do, the while clause (it is clearer to use an exit statement), case selectors of type logical, the simple if statement (keeping if then), and naming of if and select case statements. It requires a do index to be a simple local variable (not a dummy argument, a pointer, a function result, or accessed by use or host association).
For clarity, it requires each case default selector to be the final case selector of its construct.
F departs from Fortran tradition by having reserved words. All the language keywords, such as program, do, result, true, neqv, and inout, are reserved. This means that they always have the meaning specified for them in the standard and are not permitted for the names of variables, procedures, derived types, etc. All the names of intrinsic procedures are reserved, too. In all, there are about 170 such words. The programmer does not need to remember them all, since the compiler will diagnose any violations. The advantage is that the code is easier to understand and many complicated rules in the standard over the interpretation of keyword reuse can be discarded.
F also disallows the renaming of an intrinsic procedure on a use statement, to ensure that the intrinsic procedures are always referenced by their own (reserved) names.
The rules for use association in Fortran 90 are baroque. An entity may be accessed by more than one route, possibly with renaming at any point on the route. There may be more than one use statement for a module in the same scope so that the only clause does not mean what one expects.
In F no entity may be accessed by more than one name, no name may refer to more than one accessed entity (even if never referenced), and no two use statements in a scoping unit may access the same module, even indirectly where a used module uses a previously used module.
F ensures that access to a module is direct. If a module contains any use statements, it must either contain the statement
as its only other statement, or contain the statement
and give the public attribute to no accessed entities other than generic identifiers. In the first case, the module is providing a simple shorthand for a sequence of use statements. In the second case, the module is providing new definitions, possibly including extended generic identifiers, without making the objects, types, and explicit procedures that it accesses further available.
These restrictions make the rules for accessing entities from modules straightforward and make programs far easier to interpret.
All procedure interfaces in F are explicit. This means that the programmer does not have to remember the fussy rules about when an explicit interface is needed and that all procedure calls are checked at compile time.
Requiring all procedure interfaces to be explicit means that interface blocks are required for external and dummy procedures. There is therefore no external statement in F.
F has no internal procedures. They are limited anyway, since they are not permitted to be nested, passed as actual arguments, or given a generic identifier. Replacing them by module procedures is not a big burden to the programmer. An internal procedure usually accesses few entities from the host, which makes it simple to add them to the argument list. The resulting code is clearer, since the dependencies are declared.
F does not permit entry statements. They complicate the standard since a subroutine subprogram may define several subroutines and a function subprogram may define several functions, a subtlety that is lost on most readers. It is straightforward to replace subprograms containing entry statements by separate subprograms in a module.
In each dummy argument list, F requires the non-optional arguments to precede the optional arguments. The intent of each dummy argument must be specified unless it is a pointer or a procedure. Each dummy argument of a function must be of intent in unless it is a pointer or a procedure. Each procedure dummy argument of a function must be a function. Each procedure actual argument must be a module procedure.
F imposes restrictions for the sake of safety when overloading. Generic identifiers may be specified only for module procedures. No generic name for a module procedure may be identical to that of the procedure. In a module that extends an intrinsic procedure, an intrinsic statement must declare the intrinsic name. Overloading must not lead to an ambiguous call with an intrinsic name.
All the intrinsic functions produce a result that depends only on the arguments and have no side effects. Therefore any rearrangement that the compiler makes of an expression containing an intrinsic function is innocuous, including the case where it finds that the function need not be called. Fortran allows such rearrangements also for nonintrinsic functions. F therefore has rules to insure that a function is free of side effects (e.g., changing the value of an argument), apart from those needed for diagnostic purposes. If there are side effects, a subroutine should be used.
An F function must not change the value of a dummy argument, modify a value in a module, or rely on saved local data. It may perform input-output operations only with a print statement or with a formatted read or formatted write statement for an internal file or for the unit designated with an asterisk. It may invoke a subroutine only as defined assignment. Any subroutine called, either by a defined assignment or indirectly, must obey all the rules for functions except that the first argument may have intent out or inout.
F leaves the array features largely untouched. The only significant change is that all array dummy arguments must be assumed-shape or pointers. This greatly simplifies the rules for the association of dummy and actual arguments and means that copy-in copy-out is probably never performed for array arguments. It also means that there is no possibility of the dummy array being declared to be larger than the actual array. However, it means that if the full performance now available with explicit-shape dummy arrays is required, the dummy argument will have to be copied explicitly to a local array.
There are some minor restrictions on each array constructor index. It is not permitted to be a dummy argument, a pointer, a function result, or accessed by use or host association. It must not be used outside an array constructor, initialized, or saved. Also, each where statement must be the leading statement of a where construct.
It might have been expected that allocatable arrays would have been excluded, given that pointer arrays are available. However, if the full functionality of pointers is not needed, allocatable arrays are to be preferred since their use often leads to more efficient code and they do not give rise to memory leakage.
Storage association is fundamentally unsafe. This is particularly so when common and equivalence are used to share storage between data of different types. Only this week, a colleague of mine spent hours pursuing the strange behaviour of a subroutine, only to find eventually that he had associated a real variable with a double precision dummy variable.
Even when the types are the same, it is easy to make a mistake when subdividing the storage differently in different scopes. On a machine with distributed memory, this can lead to great inefficiencies since different distributions are probably needed for each different subdivision; indeed, in the HPF extension of Fortran 90, reliance on the properties of storage association requires a special directive.
F disallows storage association altogether. It does not contain any of the statements common, block data, equivalence, and sequence. It does not permit an element of an array to be an actual argument corresponding to a dummy argument that is an array.
There are few changes to the intrinsic procedures. It is assumed that the underlying machine uses the ASCII collating sequence, so the procedures achar, iachar, lge, lgt, lle, and llt are excluded. The function transfer is excluded on the grounds of being inherently unsafe. The functions dble, dim, dprod, and mod are excluded on the grounds of being redundant.
In F, no I/O statement is permitted to have an implied-do since the functionality is available either with an array constructor or with nonadvancing I/O in a do construct.
F does not include namelist.
Blanks must not appear in formats except: either side of a comma, either side of a parenthesis, after a repeat count, before a field width, or before a tab count.
No format may contain a character string edit descriptor (better done with the character string in the I/O list). The edit descriptors b, o, and z are excluded (to my regret) as are the d, e, en, g, p, x, bn, and bz edit descriptors.
No backspace, endfile, or rewind statement is permitted without a list.
There are some restrictions on the open statement. Each open statement must have a status= specifier whose value is not unknown and must have an action= specifier. Each open statement for sequential access with status old must have a position= specifier whose value is not asis. Each open statement with a status= specifier value of scratch must have an action= specifier with value readwrite. No open statement with a status= specifier value of new may have an action= specifier with value read. No open statement may be for a unit that is connected.
Cases where only one alternative is available in F further to those mentioned in Section 2 are:
So what is left after all these omissions? Apart from upward compatibility with Fortran 77, I think F meets all the objectives set out by X3J3 when it began working on Fortran 90 in the late 1970s:
The greater expressive power of the array language and of derived types is huge. The safety improvement from explicit typing, significant blanks, and explicit interfaces is also huge. Regularity is improved by the restrictions that F imposes. Dynamic storage is the most obvious extra fundamental feature compared with Fortran 77, but modules run a close second and play a particularly prominent role in F. Fortran 77 problems fixed include the lack of dynamic storage and of non-advancing I/O. The array features, largely untouched by F, allow better exploitation of massively parallel hardware. Portability is improved by the availability of parameterized types and has been improved in F by the requirement that named constants be used to specify kind values.
In summary, F is a much smaller, cleaner, and safer language that better meets the objectives of Fortran 90, apart from upwards compatibility with Fortran 77.
I would like to express my thanks to Walt Brainerd, David Epstein, Nick Gould, Dick Hendrickson, and Mike Metcalf for reading a draft of this article and suggesting improvements.
John Reid has been a member of the ANSI Fortran Committee
from 1983 to 1991 and was its Secretary from 1987
to 1990. He played an active role in the development of
Fortran 90 and co-authored one of the first books on the
language. His research has been primarily in the treatment
of sparsity, with an emphasis on the production of
general-purpose mathematical software (in Fortran) for
the Harwell Subroutine Library. He was a founder member
of the IFIP Working Group on mathematical software,
was Secretary from 1979 to 1983 and Chairman from 1983
to 1987. He now works at the Department for Computation
and Information, Atlas Centre, Rutherford Appleton
Laboratory, Didcot, Oxfordshire OX11 0QX, England.
Institut Français de Recherche
pour l'Exploitation de la MER
The designers of the F language claim that it retains all of the good things in Fortran, especially the computational efficiency. As in a previous article ("Some Fortran 90 Benchmarking Results", Fortran Journal, 1996 May/Jun) where we showed that Fortran 90 compilers can be as efficient as F77 compilers on a real world application, we tried to perform a similar exercise in order to check that respecting F rules would not impose any penalty on performance.
Thus, the most demanding routine of the application, computation of covariance matrices, was rewritten according to the F restrictions. Results for the actual application do not show any significant change in the performance for the F version. Differences can be reasonably explained by machine load only. The execution times are summarized hereafter:
System Original F90 F subroutine Sun SS20 4802 4815 IBM RS/6000 924 921 Dec Alpha 641 656
Further tests were also performed as a follow-on to the previous benchmark. These latter tests were meant to provide more insight into the optimization abilities of F90 compilers. They can thus also indicate where the F subset of methods stands with respect to the other ones, as far as performance is concerned.
Since the bottleneck subroutine is computing the dot product of single precision arrays into double precision accumulators, we decided to test a number of methods that may come to mind when using F90. These are:
SUM (DPROD(SX, SY))
2. A DO-loop over individual DPROD operations
ALPHA = 0.0D0 DO I = 1, NMAX ALPHA = ALPHA + DPROD(SX(I), SY(I)) ENDDO
4. A DO-loop over individual DBLE multiplications
ALPHA = 0.0D0 DO I = 1, NMAX ALPHA = ALPHA + DBLE(SX(I))*DBLE(SY(I)) ENDDO
5. The standard distribution BLAS DDOT, unrolled by 5
ALPHA = DDOT0 (NMAX, DBLE(SX), 1, DBLE(SY), 1)
6. The standard distribution BLAS DDOT, without unrolling
ALPHA = DDOT1 (NMAX, DBLE (SX), 1, DBLE (SY), 1)
7. The tuned BLAS DDOT from the vendor's library (sunperf for Sun Solaris 2.5, dxml for DEC, essl for IBM, and a tuned version provided by Hans Olsson (University of Lund, Sweden) with SunOS 4.1.3)
ALPHA = DDOT(NMAX, DBLE(SX), 1, DBLE(SY), 1)
8. The intrinsic DOT_PRODUCT function
ALPHA = DOT_PRODUCT (DBLE(SX), DBLE(SY))
9-14. The same as items 3 to 8, with explicit assignment to double precision arrays beforehand:
DX = DBLE (SX) DY = DBLE (SY) ALPHA = SUM (DX*DY) DX = DBLE (SX) DY = DBLE (SY) DO I = 1, NMAX ALPHA = ALPHA + DX(I)*DY(I) ENDDO DX = DBLE (SX) DY = DBLE (SY) ALPHA = DDOT0 (NMAX, DX, 1, DY, 1) DX = DBLE (SX) DY = DBLE (SY) ALPHA = DDOT1 (NMAX, DX, 1, DY, 1) DX = DBLE (SX) DY = DBLE (SY) ALPHA = DDOT (NMAX, DX, 1, DY, 1) DX = DBLE (SX) DY = DBLE (SY) ALPHA = DOT_PRODUCT (DX, DY)
15-20. The same as items 3 to 8, with the assumption that assignment to double precision arrays had been done at no cost beforehand:
ALPHA = SUM (DX*DY) DO I = 1, NMAX ALPHA = ALPHA + DX(I)*DY(I) ENDDO ALPHA = DDOT0 (NMAX, DX, 1, DY, 1) ALPHA = DDOT1 (NMAX, DX, 1, DY, 1) ALPHA = DDOT (NMAX, DX, 1, DY, 1) ALPHA = DOT_PRODUCT (DX, DY)
Further differences were searched for by using assumed size or assumed shape declaration of array arguments, and by specifying INTENT (IN) for the DDOT arguments in the function only, both in function and interface block, or omitting it in both. These specifications led to dramatic differences when using the A(:) notation to indicate the whole array (as we mentioned in the previous Fortran Journal article), but mostly disappeared when using the A notation.
Results are summarized in Figures 1 to 5. [Ed: The figures are not available here.]
In Figures 1 to 4, the performance (speed of execution) is normalized by the best method for the given system. In Figure 5, the results for the case with assumed shape arguments and fully specified intent are normalized by the advertised spec fp92 number for the system.
It's interesting to note that the DPROD intrinsic never brings any advantage over DBLE. Maybe that's one reason why DPROD isn't in F? Also, the DOT_PRODUCT function is only half as fast as the tuned DDOT.
It is very impressive that, on a given system, the worst case lays between only 5% and 25% of the best one, although it does not seem very poor programming practice. The tuned DDOT is optimal or close to optimal on all systems. It is possible to call it from an F program (at least the professional version of F), though in practice one would have to use a BLAS interface module. Fortunately for F fans, it is also possible to write the second most efficient method in F code for all of the tested systems although it might be necessary to use real(SX, kind=double) instead of DBLE(SX).
Whereas on the actual application tested earlier, the DEC compiler made the best out of the advertised specmarks, on a very specific test as this one, IBM takes the lead. The performance of the Sun compiler is only very little better than that of NAG, and is not to the credit of Sun.
Before being critical, I would like to stress that I am deeply convinced of the interest of developing F and promoting its use. We certainly need a simple subset of Fortran, easy to optimize, with cheap or free compilers, and sufficiently clean to be taught in schools and universities.
But I am an engineer, a tenant of some aspects of the Good Old Orthodox Fortran (GOOF) language. If I am to give a Fortran course, the first lesson shall be devoted to writing a program to call a subroutine from a library. It has taken 15 years to the PC community to discover the advantages of libraries, and even the DLL and object classes libraries may still not be as obviously useful as the good old object module library. Having students learn a language by writing source code for which some well-tested routines exist in well-known libraries may be a good exercise in computer science. For future engineers, I claim that it is teaching them how to waste their time.
So it is of utmost importance that libraries such as Lapack, NAG, IMSL, ..., can be called easily from F, without any performance degradation, and already at the educational level. And when examining the practical ways to achieve this, I come to the conclusion that either modules are harmful, or the current implementation of the compile-link-execute paradigm is dramatically unfit for Fortran 90, and thus for F also.
Modules, as they are, are harmful because they are multipurpose entities. Purposes are, at least:
As so different entities end-up in a single package, whereas they are used separately in the different stages of the compile-link-execute process-things such as separate compilation, dependencies management, or library building and use have become nightmares. I suspect that the designers of this part of the language overlooked the problem of the megaline range codes. In my humble opinion, a smarter design would have been different entities for the different purposes, for instance, GLOBAL POOL, COMPILE TIME CONSTANTS, CROSS PROCEDURE INFO, OBJECT METHODS, PACKAGE.
But now, we are stuck with the modules in their present form. So we are only left with the alternative of modifying the compile-link-execute paradigm. If we want F to be successful, we need libraries of modules, compilers that know how to deal with them and sophisticated make utilities that can handle them.
I would like to thank Dick Hendrickson (Imagine1, Albuquerque, USA) for his helpful suggestions and proofreading.
About the Author
Michel Olagnon (Michel.Olagnon@ifremer.fr) is working
with Ifremer, the French National Agency for Research
and Exploitation of the Seas. His main interests are
met-ocean conditions (waves, wind, currents) for engineering
applications, fatigue of materials, seismic data processing,
and of course Fortran 90. His book Traitement de données
numériques avec Fortran 90 has been published by Masson.
When work began on Fortran 90, it was clear that the revision required major additions to the language. The idea of "deprecated features" was introduced, which was supposed to permit deletions from the language as well as additions. But now, almost 20 years later, it is becoming obvious that this idea does not work in practice. Major Fortran compiler vendors find continuing user demand for even the most obscure language features, so they never delete anything-neither features officially declared obsolete in later language standards nor features inherited from earlier versions of the same vendor's compiler.
Meanwhile, recent versions of Fortran provide excellent substitutes for most of the nastier parts of traditional Fortran such as implicit data type, storage association, and arithmetic IF. Programs can now be written in standard Fortran that are as readable and reliable as in any other programming language (including the CS Department's pet of the 1980s, Pascal) without sacrificing Fortran's traditional strengths in array handling and number crunching. Except for maintaining "dusty decks" with thousands of EQUIVALENCE and COMMON statements, nobody really needs those old nasties any more. And tools are available (such as LOFT from N. A. Software and VAST/77to90 from Pacific Sierra Research) that can perform most of the work of converting legacy Fortran codes to modern style.
Compilers for Fortran 90 (or 95) are big and expensive, and they do not discourage use of inessential Fortran features--those outside the rather small subset that is actually needed for producing reliable and readable yet powerful and efficient programs. Maybe the next step should have been obvious, but it was not until a year and a half ago that somebody (Tom Lahey) took that step, and about a year later a second pioneering group (Imagine1) followed it up. The two subsets that appeared in 1995 and 1996 are truly little giants-they contain all of the most powerful features that Fortran users need, while providing compatibility with the full Fortran standard language. (The idea could not have worked without one overriding, absolute rule: a program accepted by either of these subset compilers is a standard-conforming Fortran program.)
The new Fortran subsets are excellent languages for introductory programming instruction. They have the features that are needed for teaching Computer Science (including data structures, recursion, and dynamic storage) and for applied programming in science or engineering (including arrays and complex arithmetic). They enforce safety restrictions that remain optional in the full language environment, and they provide a way to teach the good parts of Fortran without exposing students to the bad parts. They are also inexpensive (or even free, in many cases).
Yet the subsets are more than simple teaching tools. They can be used to create well organized, easily maintainable programs that are powerful and efficient. By ignoring legacy features and concentrating on the essentials, Fortran subset optimizers may be eventually achieve results that surpass those for the full language.
In early 1995, I was just completing a Fortran 90 textbook when Lahey's ELF project was brought to my attention. I immediately recognized the merit of the subset compiler idea and spent a few weeks producing a variant version of my book that omitted the non-ELF features. As one step in this process, I had to make sure that all of my examples used only the subset. This was not difficult, because the programming style that I had used in my full language textbook was already very close to ELF conformance, and it gave me a lot of practice in writing ELF programs.
Some months later, Imagine1 introduced another subset called F. As soon as I heard about it, I arranged to spend a couple of hours with David Epstein finding out what features F supports and how it relates to ELF. Two items immediately caught my attention: (1) F does not support internal procedures, and (2) IMPLICIT NONE is prohibited. I have since begun to understand the modular philosophy of F that motivated the first of these (more about this later). But the second struck me as unfortunate, for a couple of reasons.
What Fortran does not need is two mutually incompatible subsets. Inasmuch as ELF requires IMPLICIT NONE at the top of every main program and module, and the initial release of F prohibited it, nobody could write a program for either subset that would be accepted by the other. Furthermore, in my opinion migration from F to the full Fortran language was inhibited by this prohibition. I strongly believe that all full Fortran programs should begin with IMPLICIT NONE so that the compiler can detect undeclared variables. I understand that F programs do not need the statement because the compiler checks anyway. But the prohibition made it seem to me that F was designed only as a stand-alone language, for people who merely wanted to learn how to program in F, and not for those who expected to eventually program in full Fortran.
In mid summer 1996 I was gratified to learn that F now (optionally) accepts IMPLICIT NONE. At this point, I began to be really enthusiastic, and I began converting my 200 or more textbook example programs so that both of the subset compilers will accept them. (I consider it remarkable that my 200 examples exposed only one bug in the F compiler-and when I reported this obscure problem, I learned that it had already been fixed.)
At this point, I have a few hundred textbook-sized programs that are written in a Fortran subset compatible with both ELF and F. I am now undertaking a further revision of my textbook to describe this common subset, which I think of as "essential Fortran" or "eF". The book will probably be published by Unicomp before the end of 1996, and will be suitable for use in courses that teach either ELF or F. (One might even imagine a scenario where F is installed on the computer center's UNIX system and where students download ELF from www to their personal PCs.) The example program files will be made available on a diskette or by downloading.
Here are some conclusions that I have reached so far, and some opinions that I have formed.
1. F is almost a strict subset of ELF: very few ELF restrictions are not enforced by F. The most significant: a valid ELF program must have IMPLICIT NONE at the top (following the program unit header and any USE statements); it is optional in F. I feel that programmers should include this statement, as an investment in future upward migration, so I consider it a part of eF and show it in all of the examples in my book.
With regard to some of the other restrictions, I am not so sure. ELF requires STOP (in the main program) or RETURN (in a subprogram) immediately before the END statement--even if the STOP or RETURN can never be executed. Data transfer statements must be written in "long form" with a control list; since F does not permit omitted keywords in a control list, this means that the simplest input and output statements common to both subsets are read(unit = *, fmt = *) . . . and write(unit = *, fmt = *) . . . . And ELF requires a space in all compound key words, which is optional in F. All of my examples conform to these ELF requirements for the sake of compatibility, but notes in my book will show the simpler F alternatives.
2. Many F requirements are not imposed by ELF. I have categorized these into three groups that I am handling in different ways.
The first group consists of stylistic constraints; for example, F source program text must adhere to rather strict upper- and lower-case conventions; several specifiers are required in OPEN; procedure arguments and function results must be declared in separate statements; IF and CASE construct names are not supported; initialization requires explicit SAVE. For eF, I go along with F on all of these; I think that they are at least as good as any of the alternative programming style conventions that could be adopted. My book will urge stylistic consistency and will present this F style as a possible model, but it will not describe the alternatives.
(I should mention the F rule that a name, although it may be written in any combination of upper and lower case, must be written consistently throughout its scope. I agree with this rule. In my book, as in the previous full language edition, named constants are written in upper case and variable names are written with an initial capital. Compound names have an underscore followed by a capital letter.)
I think of the features in my second group as rather specialized--not normally needed (and in fact not used in any of my textbook examples) but perhaps occasionally useful. Examples are statement labels (including labelled formats), external procedures, NAMELIST, and implied DO lists for input and output. F does not support any of these, and I omit them from eF.
Finally, I have identified a few "major" features supported by ELF whose omission from F is at least annoying, in my opinion. While I concede that none of these is strictly necessary (and I managed to circumvent them in my examples), to insist on their alternatives can warp the program developer's conception of the task at hand.
Let me climb onto my soapbox for a moment. At the time of the "structured programming revolution" in the mid 1970s, I had been a Fortran programmer and a supervisor of Fortran programmers for about ten years. I fully agreed with the emphasis on programming style, but I never accepted the idea that a programming language should omit certain features just because they are easy to misuse or because an alternative is available. If a programmer's concept of a task is most naturally expressed in a certain way, forcing a different expression can introduce more errors than it saves. For example, consider a mathematician who has a recursive definition of factorial in mind, but who is forced to write an "equivalent" iterative program merely because the language does not support recursive procedures. I argue that the language design is less than ideal, even if it always provides a way to print correct answers, because it sacrifices readability and naturalness of expression, and thus compromises program reliability.
First on my list of "major" items, then, and perhaps the most controversial, is DO WHILE. Many of us were turned off by the religious claims that were made in the 1970s, to the effect that DO WHILE is the only loop construct that God really loves. The issue was further debated at considerable length before the statement was admitted into Fortran 90. Clearly, the same effect can be accomplished in a DO (forever) construct with an EXIT. Still, although the computer does the same thing in either case, the appearance or "feel" of the two program versions is quite different (as experienced users of Algol-based languages know).
My second major item is the single-statement logical IF. I think programs can be more readable if this statement is used sparingly-especially for EXIT, CYCLE, STOP, or RETURN, and perhaps occasional WRITE statements. I am considerably annoyed by the awkwardness of generating a complete IF construct (three whole lines of code) just to exit from a loop.
Thirdly, F's emphasis on modules leads to prohibitions against several things that I would sometimes like to do in a simple program. I wholeheartedly favor the profuse use of modules, which F encourages, for programs of a hundred, a thousand, or a million lines. But there are times when I need only a few lines to express my program: for example, during the first couple of lectures in a programming course or the first half chapter of a textbook--or late in the afternoon when I just want to try something before I go home. In a main program, F does not let me define a derived type, initialize a variable, or write an internal procedure. The F documentation suggests that variable initialization in a main program should be coded with an executable assignment statement--OK, but it is still not really the same thing from the programmer's viewpoint. Some people think that internal procedures were invented as a substitute for statement functions-but with F, I have to drag in the whole baggage of modules if I have one or two lines in my main program that are referenced from more than one spot. Or if there is a derived type that I need only once.
In my view, all of these features-DO WHILE, logical IF statement, internal procedures, and main programs with derived type definitions and initialization-are essential to Fortran although they are not supported by F. In my eF textbook, initial discussions will be based on common subset language features but later, in optional sections, I will present more straightforward ELF versions.
Both the ELF and F subsets prohibit function side effects such as INTENT(OUT) dummy arguments, assignment to nonlocal variables, or variable initialization (which implies SAVE). The restrictions are approximately equivalent to the pure function constraints in Fortran 95 except that some output is permitted. At first I did not like this prohibition, but I have become convinced that it is appropriate for an essential Fortran subset. Note that a full Fortran compiler, faced with a program fragment like
X = Fun(3) Y = Fun(3)
is permitted to evaluate Fun only once and assign the result twice. (Some official interpretations confirm this.) Should a subset language give the programmer a "safety net" (i.e., guaranteed execution of functions, including all side effects) that the full language environment will not provide? By analogy to my argument favoring IMPLICIT NONE, the answer must be no.
An ideal eF subset would simply require that all functions be declared PURE. At the moment, this is impossible for two reasons. (1) The subsets are now based on Fortran 90, which does not recognize the keyword PURE-but newer F95 versions of the subsets might be expected in about a year, so this difficulty is only temporary. (2) Output statements are permitted in a function, allegedly because it might be needed for debugging-the long-term solution for this is to provide adequate debugging facilities separate from the language.
On pedagogical grounds, I think it is better to explain PURE (as defined for functions in F95) than to give a list of seemingly unrelated restrictions on argument intent, initialization, etc. Meanwhile, my plan is to discuss PURE in my eF textbook, pointing out the temporary difficulty with current compilers. I will declare the PURE attribute for all functions in the printed examples, but not in the electronic versions until F95 subset compilers are released.
Release of these subsets is the greatest event for the language since Fortran 90. I would hope that some of the following principles should govern future subset development.
About the Author
Loren Meissner retired recently after 12 years as Professor
of Computer Science at the University of San Francisco.
Before joining USF, he worked for 23 years in Computer
Science and Mathematics research at Lawrence Berkeley
Laboratory. He has used Fortran since 1962 and has been
active in Fortran standardization since 1975. He has written
several computer xcience textbooks and is editor of
Fortran Forum, a newsletter published by the Association
for Computing Machinery.
Ralph Jay Frisbie
Instructor, Ventura Junior College
I am a part time instructor in the Mathematics department at Ventura College and have taught Fortran since 1982. This is a lower division course with only college algebra as a prerequisite. It is offered at least once a year. My only formal training was two hours of Fortran courtesy of an IBM salesman in 1959. Most of my following career with the U.S. Navy was simulation and data analyses using Fortran. However, after suffering through some of my own early work and seeing the abominations created by other engineering users of Fortran, I formed strong opinions on the necessity for structured coding concepts. When in the late 80's MilStd Fortran 77 became available on campus, I forbade the use of statement labels (except for FORMAT) in student programs.
When early last spring the class was scheduled for the Summer session, I made some mention on comp.lang.fortran about using the archaic HP-3000 Fortran 77 system. I received several messages about the stupidity of not utilizing Fortran 90. As a result of these messages and most especially some correspondence with Prof. Loren Meissner, I started surveying Fortran 90 compilers available for our new Pentium equipped Math lab. (Software is supplied for our students; they need buy only the text.)
Imagine1 Inc.'s F was selected because I was given the opportunity to be a beta tester of the Windows 95 version. This was clearly within my budgetary constraints, so it was selected. The proofs of the text Programmer's Guide to F by Brainerd, Goldberg, and Adams were available and it was promised to be published by the first of May. A running version of the compiler was received by the end of April and the printed copies of the text arrived on the Monday class began. For a complete description of F, please see http://www.imagine1.com/imagine1. In brief, F is a proper subset of Fortran 90. The distribution software I received also included F_World, an environment in which programs may be composed, edited, compiled, and executed. F may also be compiled and executed from the command line.
The summer session Fortran class was conducted in the Computer lab with a format of 1.5 hours lecture followed by 2 hours of lab four days per week for eight weeks. I normally require that computers be off during lecture. I used a large monitor to enter, display, debug, and execute sample programs for the students during lecture, and often left a sample program on the display during the lab.
I was rather nervous at the start of class, since I had many years experience in Fortran, but no experience with Fortran 90 or F. I had taught pointers in Pascal, but had no experience with the array operations, extended procedures of F, CYCLE and EXIT, and the whole concept of modules to replace subroutines, functions, and labeled COMMONs.
Because of my concerns, of the fact I would have to learn something new, I erred in my course outline. I failed to expect enough of the students and to assign enough exercises. I was accustomed to the old Fortran in an archaic terminal environment, and set up the assignments and course plan accordingly. I should have remembered that students will do about 90% of whatever is expected of them. F has a reasonably easy to use environment and compiles, links, loads, and begins execution within 10 seconds or so on the Pentium 100, hence the students could accomplish much more than in the older environment.
F installs very easily from the three supplied disks. Just stick Disk 1 in and select Run A:setup. Follow directions and all is easy, at least with Windows 95. Uninstall did not remove the student files created in the \usr directory, which would be a nice option. (Nor did it uninstall the group and icons from the desktop. Is that an Imagine1 problem? Or the nature of the Uninstall utility of Windows?) The F environment the students encountered was good. I used the F_World interface. This requires the students to create their modules as separate windows from the main, and to validate modules in the correct order, if there are module dependencies. No F bugs were ever found by any students. I did implement several upgrades shipped by Imagine1, but they were primarily to improve error messages. I have reported a deficiency in the random number subroutine: it seems to have a very short period when generating default precision reals. F diagnostics are pretty good. F has adopted the policy that if an error is discovered early in the listing, misspelled keyword for instance, that line is diagnosed and the scan is terminated. I support this scheme, since I routinely teach students in standard Fortran to correct the first error, ignore the rest, and obtain another error scan.
I would like an F_World environment that was a bit different. I think one intent in the interface design was to supply a fill in the blanks' template for each possible key word. This could be a nice feature, however it's current implementation is awkward - I don't like to have to retype a keyword and then the options. As one who is good on the keyboard and doesn't really have the coordination to steer a mouse reliably, I did not care for this feature of F_World, so did not use it or teach it. The other option is to directly type your modules into the F_World window in effect using F_World as an editor. For this usage, I would like to have a more standard layout of Edit (Cut/Paste/Copy) and File (Save/SaveAs/New/Old/ etc.) buttons to be more compatible with other Win95 applications such as Notepad, Word, WordPerfect, etc.)
Although the command line options of F was not used by the students, I used it often in lecture and preparation at home, editing the files with PFE32 (Programmers Free Editor). I personally preferred this method and did show it to my students. They had already found a method that worked (F_World environment, editor mode), and weren't interested in learning anything they didn't have to at the time.
I consider the actual purpose of this course, actual versus the printed/catalog purpose, to be:
This is a first course in programming. As is usual for this class, a few of the students had no prior computer experience, a few had BASIC, and one was repeating the course after dropping out of a previous Fortran 77 class taught by an unstructured engineer. With F, I met all the objectives above at least as well as I have done using Fortran or Pascal. My only real pedagogical concern is that the student does not see Fortran as it actually exists in the world. I received a very interesting comment from the student repeating the course: F was a lot better. He'd started in a class where extensive GOTOs and statement labels were used. After a couple of sessions with F's constructs, he really appreciated them. One student, who alleges he wants to major in computer science, never really got the concept of variable as a container of a value, but that is true in every programming class I've ever taught at the College. Overall, the class did well, retaining about the same percentage of the presented material as in a regular Fortran class. However, with F they had a good introduction to pointers, array operations, and modern control structures.
I do feel that F is a good introductory language. The more I worked with F, the better I liked it. I suspect F was designed by a very few people-it is small, consistent, and has no redundancies. Therefore, it's lean and mean, not overinflated like languages designed by large committees with the long history, legacy code, and compromises generated therein.
Features of F which I've appreciated include:
I strongly prefer F to Pascal as in introductory course, but I am here comparing 1960s standard Pascal (which is what we're teaching) to a 1990s language, F
There is a need for a good engineering text for F. The two books I've seen, Brainerd et al, and Metcalf and Reid, both are inadequate for engineering applications. I used D.M. Etter's Fortran 77 for Engineers and Scientists in the past and prefer the exercises in it, they are more relevant for the applied engineer. If F is to be taught in place of Fortran to general engineers, not just computer engineers, then there is a need for a new text. Both available texts are adequate; however, Metcalf and Reid devotes an entire chapter to the explanation of intrinsic procedures, whereas the appendix listing them in Brainerd is terse.
About the Author
Ralph Jay Frisbie is a retired computer engineer for the US
Navy Civil Service. He designed and developed simulations
and data analysis algorithms in Fortran to support
test and evaluation of various missiles systems. From
1971 to 1975 he was the Instructional Computer Co-ordinator,
Office of the Chancellor, California University and
Colleges. He is now a part time Instructor at Ventura Junior
1. The Numerical Algorithms Group (NAG) and Associated Computer Experts (ACE) have jointly launched the NAG/ACE Fortran 90 (SPARC) Compiler, a new optimized compiler for Sun SPARCstations running Solaris 2. The NAG/ACE Compiler provides Fortran developers and programmers with greatly enhanced performance and flexibility by combining the NAGWare Fortran 90 Compiler front end with the new CoSy generated back ends and optimizers from ACE. Additional implementations are planned for the PowerPC and other processors.
"Combining the NAG front end with the ACE back ends delivers an optimized Fortran 90 compiler which allows NAG to compete very effectively with other high performance computers on the market and particularly with the emerging native hardware Fortran 90 compilers", says Brian Ford, Director of NAG.
The NAG Fortran 90 Compiler, the world's first ISO/ANSI standard conforming Fortran 90 compiler which was launched in 1991, achieves portability using C as its intermediate language and automatically invokes the host compiler to produce object code. The NAG/ACE Fortran 90 Compiler obviates the need for intermediate source code conversion and produces target-specific final code. To achieve this, the NAG Fortran 90 Compiler has been integrated with the CoSy parallel Compilation System. The NAG/ACE Compiler also accepts HPF extensions.
Back end components in the CoSy Compilation System, like the code selector and code scheduler, are generated from processor descriptions. This leads to the quick availability of optimized and robust back-end systems for a variety of architectures. The generated compiler phases interact in parallel to product optimal code- generation strategies.
For more information, contact Kierith Ferrara-Kurth, +1-630-971-2337, email@example.com
2. Lahey Computer Systems, Inc. has announced the release of Lahey Fortran 90 (LF90) Version 3.0. Version 3.0 provides enhanced Windows programming facilities for scientists and engineers developing Fortran programs for Intel-architecture PCs.
LF90 is a complete implementation of the ANSI/ISO Fortran 90 standard. It incorporates all of Fortran 77 and adds features that make Fortran 90 the language of choice for scientific computing. LF90 combines Lahey and Intel compiler technology to produce fast, reliable programs. LF90 includes a complete set of development tools including compiler, linker, librarian, editor, debugger, make utility, video graphics library, and DOS-extender. LF90 creates programs for extended DOS, Windows 3.1x, Windows 95, and Windows NT.
LF90 Version 3.0 offers an integrated Windows development environment featuring a Fortran-smart, source-level debugger and language-sensitive editor. Version 3.0 also adds the ability to call Borland Delphi DLL routines from Fortran and Fortran DLL routines from Delphi programs.
For more information:
800-548-4778 or +1-702-831-2500
3. Salford Software, Ltd and Imagine1, Inc. have announced an F version of ClearWin to be available on Windows 95, NT, and 3.1. "Having the ClearWin Graphical User Interface (GUI) builder in the educational version of F has given F a great boost. Teachers who are dropping Pascal and were considering either Visual Basic or C++ now have a clear win with F", said Dick Hendrickson of Imagine1. Imagine1 expects to be shipping Clear-Win versions of F early in 1997.
Salford Software Ltd is providing the compiler back-end and IDE technology used in the Extended DOS, Windows 3.1x and Win32 implementations of F. David Vallance, Salford's Managing Director, was very enthusiastic about Imagine1's initiative with the F language. "Fortran will always be the language of choice for engineers, scientists and numerical specialists. The F language is both easy to learn and easy to teach. F provides a mechanism for students to learn modern programming techniques which are fully upwards compatible with the latest Fortran language standard".
4. The Computing Services Department of the University of Liverpool has developed a number of courses in Fortran 90 and High Performance Fortran (HPF). The development of these was funded by the Higher Education Funding Council's JISC New Technologies Initiative in the UK.
Both the Fortran 90 and HPF courses are available in different lengths and range from a concise hour-long seminar, which gives a broad overview of the language, to a five-day, 10-lecture version which comprehensively covers every important language feature. The courses, where appropriate, come complete with OHPs, a syllabus, detailed Lecturers Notes (for each slide), Student Course Notes (which follow the ordering of the slides) and Student Exercises. (Answers to the exercises can be obtained by special request to firstname.lastname@example.org.)
In addition to this traditional format, both courses are available as an interactive HTML Web-based tutorial. This course has been generated from the same source file as the traditional course and is structured in the same way. The slides, notes exercise and exercise solutions all form different parts of the course and the user can work through in any order.
All the courses can be reached from the main http://www.liv.ac.uk/HPC/HPCpage.html Liverpool University HPC Home Page which can be found at URL http://www.liv.ac.uk/HPC/ HPCpage.html. It should be straightforward to decide which links to choose!
Permission to use these courses for non-commercial purposes is granted, however, permission must be sought if any text is to be directly used in another document, course or program.
For more information, please contact Dr AC Marshall.
Computing Services Department, University of Liverpool.
Chadwick Building, Peach St.,
Liverpool. L69 7ZF. Tel: 0151-794 3722 (Fax: 3759).
Many sample F programs can be found at the Imagine1 F
Many sample F programs can be found at the Imagine1 F web site: http://www.imagine1.com/imagine1.