fortran essentials cs1372 auxiliary material. background fortran: formula translation fortran i...

47
FORTRAN Essentials CS1372 Auxiliary Material

Upload: jordan-flowers

Post on 26-Dec-2015

240 views

Category:

Documents


1 download

TRANSCRIPT

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:: TDO T=1,12 PRINT 100, T, T*12100 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 spacesEND 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 CodePROGRAM ch2201IMPLICIT 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, Root2INTEGER :: IFail=0LOGICAL :: 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. ENDIFEND 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

CC NEGATE AN ARRAYC IF(KFLAG .LE. -1) THEN DO 10 I=1,NN DX(I) = -DX(I) 10 CONTINUE ENDIF

FORTRAN 77 Style

!! NEGATE AN ARRAY! IF(KFLAG .LE. -1) THEN DO I = 1,NN DX(I) = -DX(I) ENDDO ENDIF

Later Style

Language Specifics – Loops

DO WHILE (Logical Expression) <block of statements> ENDDO

DO <block of statements> IF(Logical Expression) EXITENDDO

or

Language Specifics – Shared DataSimilar to global storage in MATLAB. There can be one anonymous common block (not recommended) and many named common blocks.

COMMON /NAME1/ A(100), B(100) + C(100) COMMON /NAME2/ D(250) . . COMMON /NAME1/ ABC(300)C Different usages can use different layouts

COMMON /NAME1/ A(100), B(100) + C(100) COMMON /NAME2/ D(250) . . COMMON /NAME1/ ABC(300)C Different usages can use different layouts

FORTRAN 77 Style

MODULE name1 INTEGER a(100), B(100) & c(100)END MODULE name1MODULE name2 INTEGER d(100)END MODULE name2 . .USE name1! Can’t restructure the module (a good thing!)

MODULE name1 INTEGER a(100), B(100) & c(100)END MODULE name1MODULE name2 INTEGER d(100)END MODULE name2 . .USE name1! Can’t restructure the module (a good thing!)

Later Style

Language Specifics – GOTOFrowned 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:

LOGICAL DONE = .FALSE. DO CALL USERSTUFF( DONE ) IF(DONE) GOTO 1000 ! Do something useful ENDDO1000 CONTINUE

LOGICAL DONE = .FALSE. DO CALL USERSTUFF( DONE ) IF(DONE) GOTO 1000 ! Do something useful ENDDO1000 CONTINUE

Normal goto

INTEGER IT DO IT = 1,5 GO TO (100, 200, 300, 400, 500) IT100 PRINT *, ‘it was 1’ GO TO 600200...500 PRINT *, it was 5’600 CONTINUE END DO

INTEGER IT DO IT = 1,5 GO TO (100, 200, 300, 400, 500) IT100 PRINT *, ‘it was 1’ GO TO 600200...500 PRINT *, it was 5’600 CONTINUE END DO

Later Style

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 TypesFORTRAN C/C++

integer*2 short int

integer long int or int

integer iabc(2,3) int iabc[3][2];

logical long int or int

logical*1 boolC++, One byte)

real float

real*8 double

complex struct{float r, i;}

double complex struct{double dr, di;}

character*6 abc char abc[6];

parameter #define PARAMETER value

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

testF.f testC.c

program test

integer ii, jj, kk common/ijk/ ii, jj, kk real*8 ff character*32 cc

ii = 2 jj = 3 kk = 4 ff = 9.0567 cc = 'Example of a character string'

write(6,10) ii, ff10 format('ii= ',i2,' ff= ',f10.4)

call abc(ii) write(6,20) ii20 format('ii= ',i2)

write(6,30) ii, jj, kk call doubleIJK(cc)

write(6,30) ii, jj, kk30 format('ii= ',i2,' jj= ', i2, ' kk= ', i2) write(6, 40) cc40 format(a32) stop end

subroutine abc(jj) jj = jj * 2 return end

#include <stdio.h>

extern struct{ int ii, jj, kk;} ijk_;

int doubleijk_(char *cc, int ll){ printf("From doubleIJK: %s\n",cc);

ijk_.ii *=2; ijk_.jj *=2; ijk_.kk *=2;

return(1);}

Example: FORTRAN calling C

Example: FORTRAN calling C

Running this exampleCompile: >> 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.0567

ii= 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 testC.cpp testF.f

#include <iostream>

using namespace std;

extern"C" {void fortfunc_(int *ii, float *ff);}

main(){

int ii=5; float ff=5.5;

fortfunc_(&ii, &ff);

return 0;}

subroutine fortfunc(ii,ff) integer ii real*4 ff

write(6,100) ii, ff 100 format('ii=',i2,' ff=',f6.3)

return end

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

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. #ifdef _cplusplus extern"C" { #endif . . place declarations here . . #ifdef __cplusplus } #endif

Your Worst NightmarePROGRAM ouchIMPLICIT NONE! Define your variablescharacter*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 DOEND

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)

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 and better 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.

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”