500 likes | 734 Views
FORTRAN Essentials. CS1372 Auxiliary Material. Background. FORTRAN: FORmula TRANslation Fortran I written 1954-1957 First successful HLL Team at IBM lead by John Backus Changed everything Fortran II released 1958 Fortran III never released Fortran IV released 1962
E N D
FORTRAN Essentials CS1372 Auxiliary Material
Background • FORTRAN: FORmula TRANslation • Fortran I written 1954-1957 • First successful HLL • Team at IBM lead by John Backus • Changed everything • Fortran II released 1958 • Fortran III never released • Fortran IV released 1962 • Version G in common use in the mid 60's • Version H highly optimizing. Written in Fortran IV Ver G! • Fortran 66 Standard released in 1966 (ANSI) • First HLL standard in the world
Background • FORTRAN 77 (1978) • Fixed a number of shortcomings in Fortran 66 • FORTRAN 90 (1991) • Took too long and allowed C and C++ major inroads • FORTRAN 95 • Minor revision plus High Performance Fortran • FORTRAN 2003 • Latest version...major revision • 2007: John Backus - Leader of Fortran Project dies at 82
References • http://www.kcl.ac.uk/kis/support/cit/fortran/ provides more information than you could possibly make use of. • http://www.star.le.ac.uk/~cgp/prof77.html#tth_sEc4.6 is a web version of one of the original text books. • Good text book: “Introduction to Programming with FORTRAN”: Chivers and Sleightholme; Springer Press
The Ultimate Reference http://www.ee.ryerson.ca/~elf/hack/realmen.html
Background • FORTRAN was designed when punched cards were the source code input medium for computers • Each card was one line of code. Large programs were contained in file cabinets full of cards
Restricted Character Set • Only numbers, upper case letters, .,+-*/ • So what about: • ‘THIS IS TEXT’ -> 12HTHIS IS TEXT Yes, you had to count the letters in the string • >, <, & etc -> .GT. .LT. .AND. etc • Later versions added the quote character but retained the logical operator syntax
Design Goals • FORTRAN is designed for speed – more so even than C – and many of its irritating language features derive from this goal. • It is case insensitive, unlike almost all modern languages. • Earlier versions did not permit recursion
Program Modules • The main program is a PROGRAM and appears first in the source file • SUBROUTINES are CALLED by the main program or other SUBROUTINES, and return nothing. They can, however, “send values back” via parameters.
Program Modules (cont) • FUNCTIONS can both return values and return data via parameters. The data return feature is really only useful if you want to use the result directly in an expression or as a function parameter. • Parameters are always passed by reference • In later versions, you express the INTENT of a parameter to be IN, OUT, or INOUT.
Swap (PBR) SUBROUTINE SWAP(INT I, INT J) INT T; T = I I = J J = T RETURN END
Implicit Variable Typing • In the original language, variables did not need to be predefined for type. • If the variable name started with I .. N, it was assumed to be an integer. • Starting with other letters, it was assumed to be real. • You could override the default typing but real programmers never did. • You frequently see IMPLICIT NONE at the head of a program indicating that all variables should be explicitly typed.
FORTRAN BADNESS • Early versions had fascinating pass by reference bug! SUBROUTINE WEIRD(INT I) I = I * 2 RETURN END
FORTRAN BADNESS INT K, J K = 7 WEIRD(K) WEIRD(1) J = 1 + 1 + 1
FORTRAN BADNESS • Did not require variables to be declared • Had no reserved words • Spaces mean nothing (i.e. not required) DO 10 I = 1,1000 TOTAL = TOTAL + SENSOR 10 CONTINUE AVG = TOTAL/1000.
I/O In General • I/O functions need two parameters: a unit number and a format line number. • In the punched card days when there was no console, unit 5 was the card reader, unit 6 the line printer and unit 7 the card punch • When the console became available, unit * was the equivalent of stdin or stdout respectively.
Output Commands • PRINT * works like MATLAB’s disp() function – shows you values in arbitrary form. • PRINT <format line>, <parameters>works like MATLAB’s fprintf() function. For example, INTEGER:: T DO T=1,12 PRINT 100, T, T*12 100 FORMAT(‘ ‘,I3,’ * 12 = ‘, I3) END DO
Input Commands • The READ command in its fullest form is: READ(UNIT=<unit>, FMT=<ln no>) <params> • It is frequently abbreviated to: READ(<unit>, <ln no>) <params> or: READ <fmt>, <params> (unit assumed *) • For example: DO I = 1,N READ 100, X(I), TEMP, Y(I) 100 FORMAT (2X, I2, A, I3) ! X means skip the spaces END DO
Development Environment • The development environment consists of whatever text editor you like and a command window that is used to invoke the compiler. • You compile a program using f95 (once it is installed and licensed) • The –o switch on the compiler lets you specify the name of the executable. • If you don’t specify an output file, it produces an executable file a.exe. • You then run the program by typing the name of the executable file.
Example Code PROGRAM ch2201 IMPLICIT NONE ! Simple example of the use of a main program and two ! subroutines. One interacts with the user and the ! second solves a quadratic equation, ! based on the user input. REAL :: P, Q, R, Root1, Root2 INTEGER :: IFail=0 LOGICAL :: OK=.TRUE. CALL Interact(P,Q,R,OK) IF (OK) THEN CALL Solve(P,Q,R,Root1,Root2,IFail) IF (IFail == 1) THEN PRINT *,' Complex roots' PRINT *,' calculation abandoned' ELSE PRINT *,' Roots are ',Root1,' ',Root2 ENDIF ELSE PRINT*,' Error in data input program ends' ENDIF END PROGRAM ch2201
Example Code (Subroutines) SUBROUTINE Interact(A,B,C,OK) IMPLICIT NONE REAL , INTENT(OUT) :: A REAL , INTENT(OUT) :: B REAL , INTENT(OUT) :: C LOGICAL , INTENT(OUT) :: OK INTEGER :: IO_Status=0 PRINT*,' Type in the coefficients A, B AND C' READ(UNIT=*,FMT=*,IOSTAT=IO_Status) A, B, C IF (IO_Status == 0) THEN OK=.TRUE. ELSE OK=.FALSE. ENDIF END SUBROUTINE Interact SUBROUTINE Solve(E,F,G,Root1,Root2,IFail) IMPLICIT NONE REAL , INTENT(IN) :: E REAL , INTENT(IN) :: F REAL , INTENT(IN) :: G REAL , INTENT(OUT) :: Root1 REAL , INTENT(OUT) :: Root2 INTEGER , INTENT(INOUT) :: IFail ! Local variables REAL :: Term REAL :: A2 Term = F*F - 4.*E*G A2 = E*2.0 ! if term < 0, roots are complex IF(Term < 0.0)THEN IFail=1 ELSE Term = SQRT(Term) Root1 = (-F+Term)/A2 Root2 = (-F-Term)/A2 ENDIF END SUBROUTINE Solve
Results List the Directory Compile the Program Run the Program
ANCIENT HISTORY IF(X)10, 20, 30 10 CONTINUE PRINT *, 'Negative' GO TO 40 20 CONTINUE PRINT *, 'Zero' 30 CONTINUE PRINT *, 'Positive' 40 CONTINUE
ANCIENT HISTORY IF(X .GE. 42) GO TO 100 C** HANDLE X < 42 HERE GO TO 200 100 CONTINUE C** HANDLE X >= 42 HERE 200 CONTINUE
Language Specifics – Loops FORTRAN 77 Style C C NEGATE AN ARRAY C IF(KFLAG .LE. -1) THEN DO 10 I=1,NN DX(I) = -DX(I) 10 CONTINUE ENDIF Later Style ! ! NEGATE AN ARRAY ! IF(KFLAG .LE. -1) THEN DO I = 1,NN DX(I) = -DX(I) ENDDO ENDIF
Language Specifics – Loops DO WHILE (Logical Expression) <block of statements> ENDDO or DO <block of statements> IF(Logical Expression) EXIT ENDDO
Language Specifics – Shared Data Similar to global storage in MATLAB. There can be one anonymous common block (not recommended) and many named common blocks. FORTRAN 77 Style Later Style COMMON /NAME1/ A(100), B(100) + C(100) COMMON /NAME2/ D(250) . . COMMON /NAME1/ ABC(300) C Different usages can use different layouts MODULE name1 INTEGER a(100), B(100) & c(100) END MODULE name1 MODULE name2 INTEGER d(100) END MODULE name2 . . USE name1 ! Can’t restructure the module (a good thing!)
Language Specifics – GOTO Frowned upon in polite society. Early FORTRAN had 2 versions: the normal GO TO that survives in C today, and the Computed go to with many of the characteristics of switch: Normal goto Later Style LOGICAL DONE = .FALSE. DO CALL USERSTUFF( DONE ) IF(DONE) GOTO 1000 ! Do something useful ENDDO 1000 CONTINUE INTEGER IT DO IT = 1,5 GO TO (100, 200, 300, 400, 500) IT 100 PRINT *, ‘it was 1’ GO TO 600 200 . . . 500 PRINT *, it was 5’ 600 CONTINUE END DO
Interfacing to C/C++ • A really nasty exercise that is done frequently. • Issues: • Data type names, sizes and layout • Function names, especially C++ • Parameter Passing • Common Blocks / Modules • Byte alignment in structures (a concern with migrating C code also)
Language Specifics – Data Types Note that the array dimension ordering is reversed from C, and indexing is from 1, not 0
Linking FORTRAN and C Subroutines • The entry point names for some FORTRAN compilers have an underscore appended to the name. This is also true for common block/structure names. FORTRAN: call subrA( ... ) C: subra_( ... ) • The compiler flags "-fno-underscore" and "-fno-second-underscore" will alter the default naming in the object code and thus affect linking. One may view the object file with the command nm (i.e.: nm file.o). • Case in FORTRAN is NOT preserved and is represented in lower case in the object file.
Function Arguments • All arguments in FORTRAN are passed by reference and not by value. Thus C must pass FORTRAN arguments as a pointer: FORTRAN: subrA(I, x); C: subra_(int *I, float *x)
Character Arguments • FORTRAN Character variables are not null terminated; you must provide the C program with its length in a separate variable. FORTRAN: subrA(strA, strB); C: int la = strlen(srta); int lb = strlen(srtb); subra_(char *stra, int la, char *strb, int lb);
Common Blocks • FORTRAN common blocks (must be named) are equivalent to extern struct of the same name. Must be referenced first by FORTRAN otherwise, the extern can’t find its reference. FORTRAN: DOUBLE PRECISION :: X INTEGER :: A, B, C COMMON /ABC/ X, A, B, C C: extern struct { double x; int a, b, c; } abc_;
Byte Alignment • Byte alignment can be a source of data corruption if memory boundaries between FORTRAN and C/C++ are different. • Each language may also align structure data differently. • The best way to preserve the alignment of memory between the C/C++ "struct" and FORTRAN "common block" is by specifying the variables in the exact same order and exactly matching the size of each variable. • It is best to order the variables from the largest word size down to the smallest. • Start with "double" followed by "float" and "int“ with bool and byte aligned data listed last.
Byte Alignment Example FORTRAN: INTEGER :: A DOUBLE PRECISION :: D, E LOGICAL*1 :: FLAG COMMON/ABC/ A, D, FLAG, B, E C: extern struct{ int a; double d; bool flag; int b; double e; } abc_; • Has a high probability of problems due to the sizes of LOGICAL*1 and bool, for example.
Forcing alignment with compiler arguments • Use the following compiler flags to force a common memory alignment and padding to achieve a common double word alignment of variables: • Intel FORTRAN: -warn alignments -align all -align rec8byte • Intel C/C++: -Zp8 • GNU g++: -Wpadded -Wpacked -malign-double -mpreferred-stack-boundary=8 GNU g77: -malign-double
Running this example Compile: >> f95 -c testF.f >> gcc -c testC.c >> f95 -o test testF.o testC.o Note: If there is use of C/C++ standard libraries you may have to include the following linking arguments: -lc or -lstdc++ Run: >> run ./test ii= 2 ff= 9.0567ii= 4ii= 4 jj= 3 kk= 4From doubleIJK: Example of a character stringii= 8 jj= 6 kk= 8Example of a character string
C++ calling a FORTRAN function Compile: >> f95 -c testF.f >> g++ -c testC.cpp >> g++ -o test testF.o testC.o -lg2c Run: >> run ./test ii= 5 ff= 5.500
Name Mangling • C++ functions are unique not only by their name, but also by the types of the parameters. • C++ names in the object code therefore look something like this: _sin_double • When mixing Fortran with C++, this name mangling must be prevented.
Your Worst Nightmare PROGRAM ouch IMPLICIT NONE ! Define your variables character*14 str = ‘abcdefg’ ! Call your subroutine CALL HIDEOUS(str, 7) Print *, str, ‘ contained ’, 7, ’ letters’ END PROGRAM ouch SUBROUTINE hideous(STR, N) L = N DO WHILE (N .GT. 0) STR(N) = STR(L-N+1) N = N - 1 END DO END Result: gfedcba contained 0 letters !!!!!!!!!!!!!!
Is FORTRAN still in use? Results of a NASA study on the performance of OO FORTRAN 90 (ADT) vs the original FORTRAN 77. (NAG/Unix is licensed at Tech) Ratio of using the F90 abstract data type (ADT) versusthe standard F77 way of passing array components
Is FORTRAN still in use? From “Modernizing Fortran 77 Legacy Codes,” a NASA JPL report: Our methodology is based on Fortran 90/95, because it has the modern features we desire, while still maintaining backward compatibility. We make use of Fortran 90 language features such as modules, derived types, and dynamic array objects. Embedding the older code inside the interface libraries encapsulates the implementation details of the legacy code, while adding dynamic features and additional safety checks. This also enables multiple authors to work on pieces of the code without interfering with one another andbetter reflects the problem domain. The new code can evolve toward an object-oriented design, if that desired. Once the new superstructure works correctly, there is always the option of replacing individual pieces of the legacy code. In our presentation, we will describe our methodology and demonstrate its success for … an optical modeling code important to NASA's Next Generation Space Telescope Project and Space Interferometry Missions. Ratio of using the F90 abstract data type (ADT) versusthe standard F77 way of passing array components
FORTRAN Performance • This sample from a report from Rensselaer Polytechnic Institute
Summary • FORTRAN is still used today: • Tons of legacy code that still works • If you are interested, run a Google search for “written in FORTRAN 77”. • The language syntax is not pretty • It was built for speed a long time ago • It’s very risky to use the word “never” as in • “I’ll never drive a VW Beetle again” or • “I’ll never need to mess with that language”