Fortran (also FORTRAN) is a general-purposeSince FORTRAN 77, which introduced the CHARACTER data type., proceduralSince FORTRAN II (1958)., imperative programming language that is especially suited to numeric computation and scientific computing. Originally developed in the 1950s, Fortran was used extensively in scientific and engineering applications, and is still in use in many niches such as climate modeling and molecular dynamics modeling [http://www.fisica.uniud.it/~ercolessi/md/md/node61.html.
Fortran (an acronym derived from its original official name, The IBM Mathematical Formula Translating System) encompasses a lineage of versions, each of which evolved to add extensions to the language while retaining compatibility with previous versions. Successive versions have added support for processing of character-based data (FORTRAN 77), array programming (Fortran 90), module-based programming (Fortran 90), object-based programming (Fortran 90), and object-oriented and generic programming (Fortran 2003).
The names of earlier versions of the language through FORTRAN 77 were conventionally spelled in all-caps (FORTRAN 77 was the last version in which the use of lowercase letters in keywords was strictly nonstandard). The capitalization has been dropped in referring to newer versions beginning with Fortran 90. The official language standards now refer to the language as "Fortran."
The language was widely adopted by scientists for writing numerically intensive programs, which encouraged compiler writers to produce compilers that could generate faster and more efficient code. The inclusion of a complex number data type in the language made Fortran especially suited to technical applications such as electrical engineering.
By 1960, versions of FORTRAN were available for the IBM 709, 650, 1620, and 7070 computers. Significantly, the increasing popularity of FORTRAN spurred competing computer manufacturers to provide FORTRAN compilers for their machines, so that by 1963 over 40 FORTRAN compilers existed. For these reasons, FORTRAN is considered to be the first, widely used cross-platform programming language.
The development of FORTRAN paralleled the early evolution of compiler technology; indeed many advances in the theory and design of compilers were specifically motivated by the need to generate efficient code for FORTRAN programs.
DIMENSION and EQUIVALENCE statements
IF statement; IF statements for checking exceptions (ACCUMULATOR OVERFLOW, QUOTIENT OVERFLOW, and DIVIDE CHECK); IF statements for checking sense switches and sense lights.
GO TO, computed GO TO, ASSIGN, assigned GO TO
DO loops
FORMAT, READ, READ INPUT TAPE, WRITE, WRITE OUTPUT TAPE, PRINT, PUNCH,
READ TAPE, READ DRUM, WRITE TAPE, WRITE DRUM
END FILE, REWIND, and BACKSPACE
PAUSE, STOP, and CONTINUE,
FREQUENCY statement for optimization hints
It is interesting to note that the main branching construct, the three-way arithmetic IF statement, directly corresponded to the branch instruction on the 704 - which was also a three-way branch.
SUBROUTINE, FUNCTION, END
CALL, and RETURN
COMMON
Over the next few years, FORTRAN II also incorporated support for DOUBLE PRECISION and COMPLEX data types.
READ INPUT TAPE, while adding new features such as a LOGICAL data type, logical Boolean expressions and the logical IF statement as an alternative to the arithmetic IF statement. FORTRAN IV was eventually released in 1962, first for the IBM 7030 ("Stretch") computer, followed by versions for the IBM 7090 and 7094.
SUBROUTINE, FUNCTION, and BLOCK DATA program units
INTEGER, REAL, DOUBLE PRECISION, COMPLEX, and LOGICAL data types
COMMON, DIMENSION, and EQUIVALENCE statements
DATA statement for specifying initial values
EXTERNAL (e.g., library) functions
GOTO, assigned GOTO, and computed GOTO statements
IF and arithmetic (3-way) IF statements
DO loops
READ, WRITE, BACKSPACE, REWIND, and ENDFILE statements for sequential I/O
FORMAT statement
CALL, RETURN, PAUSE, and STOP statements
DATA and FORMAT statements, and as actual arguments to procedures
CHARACTER data type, with vastly expanded facilities for character input and output and processing of character-based data
IMPLICIT statement
IF statement, with optional ELSE and ELSE IF clauses, to provide improved language support for structured programming
OPEN, CLOSE, and INQUIRE statements for improved I/O capability
PARAMETER statement for specifying constants
SAVE statement for persistent local variables
An important practical extension to FORTRAN 77 was the release of MIL-STD-1753 in 1978. This specification, developed by the U. S. Department of Defense, standardized a number of features implemented by most FORTRAN 77 compilers but not included in the ANSI FORTRAN 77 standard. These features would eventually be incorporated into the Fortran 90 standard.
DO WHILE and END DO statements
INCLUDE statement
IMPLICIT NONE variant of the IMPLICIT statement
The development of a revised standard to succeed FORTRAN 77 would be repeatedly delayed as the standardization process struggled to keep up with rapid changes in computing and programming practice. In the meantime, as the "Standard FORTRAN" for nearly fifteen years, FORTRAN 77 would become the historically most important dialect.
RECURSIVE procedures
ALLOCATABLE attribute, and ALLOCATE and DEALLOCATE statements, for dynamic memory allocation
POINTER attribute, pointer assignment, and NULLIFY statement to facilitate the creation and manipulation of dynamic data structures
CASE construct for multi-way selection
EXIT and CYCLE statements for "breaking out" of normal DO loop iterations in an orderly way
FOR ALL and nested WHERE constructs to aid vectorization
PURE and ELEMENTAL procedures
An important supplement to Fortran 95 was the ISO technical report TR-15581: Enhanced data type facilities, and informally known as the Allocatable TR. This specification defined enhanced use of ALLOCATABLE arrays, prior to the availability of fully Fortran 2003-compliant Fortran compilers. Such uses include ALLOCATABLE arrays as derived type components, in procedure dummy argument lists, and as function return values. ALLOCATABLE arrays are preferable to POINTER-based arrays because ALLOCATABLE arrays are required by Fortran 95 to be automatically deallocated when they go out of scope, eliminating the possibility of memory leakage. In addition, aliasing is not an issue for optimization of array references, allowing compilers to generate faster code than in the case of pointers.
A comprehensive summary of the new features of Fortran 2003 is available at the ISO Fortran Working Group (WG5) official Web site, and may be downloaded directly as a PDF file or gzipped PostScript file.
C (or asterisk, as permitted by FORTRAN 77) was punched in column 1, the card was a comment line, ignored by the compiler
1–99999) could be punched in columns 1–5 if needed
As programs moved to magnetic media, and interactive terminals replaced keypunches and card readers, fixed-form source became increasingly restrictive. Fixed form also allowed certain errors to be silently accepted by compilers - leading to hidden bugs. Fortran 90 introduced free-form source to resolve these problems. As of Fortran 95, fixed-form source is now considered a deprecated feature of the language.
GOTO statement could equivalently be (and very often was) punched as GO TO. Likewise, a statement such asWith FORTRAN 77, it became standard practice to insert a comma between the first statement number and the DO variable; however, this comma could be omitted for compatibility with FORTRAN 66.
DO 1 I = 1, 10
could equivalently be punched as:
DO1I=1,10
Minor typos could lead to wildly different semantics; for example, if the comma above were inadvertently punched as a period, the above statement (intended to implement a DO loop) would be interpreted as the assignment statement
DO1I = 1.10
This would not be flagged by the compiler as an error, due to the implicit typing mechanism (see below) which allows variables to be declared by their first use.
In addition, in order to save the keypunch operator the trouble of punching lots of zeroes in input data cards, blanks in numeric data fields were, depending on the context and on the particular compiler, interpreted by FORTRAN input statements as zeroes.
As part of the Fortran 90 free-form source form, blank significance is now required. The older rules were retained for the now-deprecated fixed-form source. Also as of Fortran 90, implicit typing can be disabled.
GOTO statementsGOTO statement to implement control structures. For example, the number immediately following the DO keyword above specified the statement number of the last statement enclosed in the body of the DO loop.
Using the IF statement combined with the GOTO statement, it was possible to implement looping constructs such as a while (condition) do ... construct (with the test at the top, illustrated here using the block IF statement introduced with FORTRAN 77):
1 IF (condition) THEN executable_statements GOTO 1 END IF
as well as a repeat ... until (condition) construct (with the test at the bottom, illustrated here using the logical IF statement introduced with FORTRAN 66):
1 executable_statements IF (.NOT.condition) GOTO 1
Statement numbers were also required as targets to handle I/O exceptions, such as those handled by the END= and ERR= specifiers in I/O statements such as READ and WRITE, among others.
&.
As of Fortran 95, the older fixed-form source has been considered deprecated.
Both the FORTRAN 66 and FORTRAN 77 standards required compilers to support at least six characters for identifiers, though many compilers supported longer identifiers. Fortran 90 guaranteed support for identifiers of up to 31 characters, while Fortran 2003 extended this support to 63 characters.
I through N were implicitly assumed to be INTEGER variables, whereas all other variables were assumed to be REALs. (In mathematics, the symbols i through n are typically used as (integer) subscripts and superscripts.) This implicit typing mechanism could be overridden using an IMPLICIT statement to change the default types associated with variables based on their initial letter.
Alternatively, explicit variable declarations could be used to declare the types of variables. Explicit declarations were also necessary for variables of type other than REAL and INTEGER (namely for the DOUBLE PRECISION, COMPLEX, LOGICAL, and CHARACTER data types).
Because simply mistyping a variable name effectively caused a new variable to be declared according to the implicit typing rules above (assuming the mistyped name was not previously declared), later compilers provided an IMPLICIT NONE statement to allow turning off the implicit typing mechanism, forcing all variables to have to be declared before use. The IMPLICIT NONE statement became standard with Fortran 90. Most Fortran coding standards mandate the use of IMPLICIT NONE.
IF statementIF statement:
IF (expression) n1, n2, n3
The conditional expression was an INTEGER- or REAL-valued numeric expression, and control would be passed to statement number n1, n2, or n3 depending on whether the expression was negative, zero, or positive, respectively.Note that in the case of a REAL-valued expression, the usual caveat regarding tests for floating-point equality applies, i.e., an expression mathematically expected to evaluate to zero may not exactly equal zero due to round-off error and the limited internal precision of floating-point arithmetic.
Although seemingly arcane, the arithmetic IF statement was convenient shorthand for branching based on the three possible conditions of , , or , in the case where the test expression was of the form X - Y. Thus, one was often taught mentally to view a statement of the form
IF (X - Y) 100, 200, 300
as FORTRAN idiom for the following group of equivalent statements (here, expressed as logical IF statements, which were not introduced until FORTRAN 66):
IF (X .LT. Y) GO TO 100 IF (X .EQ. Y) GO TO 200 IF (X .GT. Y) GO TO 300
Obviously, in the case of "less-than-or-equal-to" or "greater-than-or-equal-to," the first two or last two, respectively, of the GOTO targets would be the same.
This feature is described for historic reasons, as it is rarely, if ever, used in modern Fortran
IF statementsIF statement. This allowed most Fortran statements, including the GO TO statement, to be conditionally executed:
IF (expression) executable_statement
FORTRAN 77 introduced the block IF statement with optional ELSE IF and ELSE clauses to support structured programming:
IF (expression) THEN executable_statements ELSE IF (expression) THEN executable_statements ELSE executable_statements END IF
case statementcase selection structure to implement multi-way branches. The following artificial example mimics the arithmetic IF statement above (but only in the case of an integer-valued test expression, as values such as or would fall through the cracks in this example):
select case(i - j)
case(:-1)
! Former code jumped to by GOTO 100
case(0)
! Former code jumped to by GOTO 200
case(1:)
! Former code jumped to by GOTO 300
end select
ENTRY statementENTRY statement, which allowed a program to jump to an arbitrary point within a subprogram, violating the single-entry control flow philosophy of modern programming practice. In the example below, FUN is a function expecting three variable arguments, while FUNALT is an alternate entry point invoked with only two arguments; for illustration, the third argument is given a default value for the alternate entry point:
FUNCTION FUN(A, B, OPTARG) statements specific to FUN GOTO 1 ENTRY FUNALT(A, B) OPTARG = 0 statements specific to FUNALT 1 statements common to both RETURN END
Equally as interesting, FORTRAN also supports alternate RETURN, where a subprogram can specify an alternate point to which to return, rather than the original point at which the subprogram was invoked.
As of Fortran 95, both ENTRY and alternate RETURN are now considered deprecated features.
GO TOINTEGER nextstmt ASSIGN 45 TO nextstmt 10 GO TO nextstmt 15 ASSIGN 90 TO nextstmt GO TO 10 25 ASSIGN 15 TO nextstmt GO TO 10 35 ASSIGN 25 TO nextstmt GO TO 10 45 ASSIGN 35 TO nextstmt GO TO 10 90 CONTINUE
This silly example jumps to 45 (after the first assign), which reassigns the variable and jumps to 10 to execute the indirect jump to 35, and so on until statement 15 breaks out to the continue at statement 90. Since Fortran 95, implementions no longer recognize this feature. IBM Fortran manual for GO TO (assigned)
More usefully, FORMAT statements may be assigned
SUBROUTINE occurences (N)
INTEGER fmt
10 FORMAT ('No occurrences found')
11 FORMAT ('One occurrence found')
12 FORMAT (I4, ' occurrences found')
IF (N-1) 20, 21, 22 ! if N<1, goto 20; if N=1, goto 21; if N>1, goto 22
20 ASSIGN 10 to fmt
GOTO 30
21 ASSIGN 11 to fmt
GOTO 30
22 ASSIGN 12 to fmt
30 WRITE (6, fmt) N
END SUBROUTINE
Many implementations did not protect against invalid assignments or use of assigned variables, even allowing arithmetic. SUBROUTINE crash4ways INTEGER dest GOTO dest ! jumps to random location pointed to by uninitialized variable dest 10 FORMAT ('message') ASSIGN 10 TO dest GOTO dest ! jumps to data 20 CONTINUE ASSIGN 20 TO dest PRINT dest ! uses machine code at label 20 as format specification; ! almost certain to give runtime error "invalid format" 30 ASSIGN 30 TO dest dest = dest * 3 GOTO dest ! a random jump likely to fault on illegal instructions or data
Such machine-specific extensions have either disappeared over time or have had elements incorporated into the main standards; the major remaining extension is OpenMP, which is a cross-platform extension for shared memory programming. One new extension, CoArray Fortran, is intended to support parallel programming.
Among the more popular specialized Fortran-based languages that evolved over time are SAS, for generating statistical reports, and SIMSCRIPT, for modeling and simulating large discrete systems.
F was designed to be a clean subset of Fortran 95 that attempted to remove the redundant, unstructured, and deprecated features of Fortran, such as the EQUIVALENCE statement.
Early FORTRAN syntax (prior to Fortran 90) did not in general treat blanks as significant, which made writing robust and efficient lexical analyzers for Fortran difficult. Subsequent developments such as free-form source have largely resolved these issues.
Fortran was designed to create fast executable code for scientific programming. One reason for this attitude was that it was intended to compete against hand-written assembly language from the start. In scientific computing, this means that efficient array processing is of critical concern. Many other languages do not treat arrays, especially multi-dimensional arrays, as cleanly and simply as Fortran does.
In particular, Fortran data items are not allowed to alias one another, except in very well-defined and explicit situations. This allows a Fortran compiler much flexibility to generate very efficient code, by default, compared to pointer-intensive languages. Explicit use of certain C features, such as the register keyword and the C99 restrict keyword can mitigate some of the performance problems of C.
SAVE statement to allow a programmer to explicitly state which variables are required to retain their values when they go out of scope. Likewise, Fortran 90 introduced RECURSIVE procedures. In a recursive procedure, non-SAVEd local variables must be unique for each active instance of the procedure.
.f extension (for FORTRAN 66 or FORTRAN 77 source, although the FORTRAN 66 dialect may have to be selected specifically with a command-line option) or .f90/.f95 extension (for Fortran 90/95 source, respectively).
The Snoopy Calendar program is the classic Fortran program referenced in many nostalgic items on computer history (eg. Real Programmers Don't Use Pascal). This version can also be run on the IBM 1130 emulator.
C FORTRAN IV WAS ONE OF THE FIRST PROGRAMMING C LANGUAGES TO SUPPORT SOURCE COMMENTS WRITE (6,7) 7 FORMAT(12HHELLO, WORLD) STOP END
This program prints "HELLO, WORLD" to Fortran unit number 6, which on most machines was the line printer or terminal. (The card reader or keyboard was usually connected as unit 5). The number 7 in the WRITE statement refers to the statement number of the corresponding FORMAT statement. FORMAT statements may be placed anywhere in the same program or function/subroutine block as the WRITE statements which reference them. Typically a FORMAT statement is placed immediately following the WRITE statement which invokes it; alternatively, FORMAT statements are grouped together at the end of the program or subprogram block. If execution flows into a FORMAT statement, it is a no-op. So the example has only two executable statements: WRITE and STOP.
The initial 12H in the FORMAT statement in the above example defines a Hollerith constant, here meaning that the 12 characters immediately following are to be taken as a character constant (note that the Hollerith constant is not surrounded by delimiters). (Some compilers also supported character literals enclosed in single quotes, a practice that came to be standard with FORTRAN 77.)
FORMAT statements. Comment lines could be indicated with either a C or an asterisk in column 1.
PROGRAM HELLOW * The PRINT statement is like WRITE, * but prints to the standard output unit PRINT '(A)', 'Hello, world' STOP END
program HelloWorld write (*,*) 'Hello, world!' ! This is an inline comment end program HelloWorld
PROGRAM CMPLXD IMPLICIT COMPLEX(X) PARAMETER (PI = 3.141592653589793, XJ = (0, 1)) DO 1, I = 0, 7 X = EXP(XJ * I * PI / 4) IF (AIMAG(X).LT.0) THEN PRINT 2, 'e**(j*', I, '*pi/4) = ', REAL(X), ' - j',-AIMAG(X) ELSE PRINT 2, 'e**(j*', I, '*pi/4) = ', REAL(X), ' + j', AIMAG(X) END IF 2 FORMAT (A, I1, A, F10.7, A, F9.7) 1 CONTINUE STOP END The above example is intended to illustrate the following:
IMPLICIT statement can be used to specify the implicit type of variables based on their initial letter if different from the default implicit typing scheme described above. In this example, this statement specifies that the implicit type of variables beginning with the letter X shall be COMPLEX.
PARAMETER statement may be used to specify constants. The second constant in this example (XJ) is given the complex-valued value , where is the imaginary number .
DO statement specifies the number of the last statement considered to be within the body of the DO loop. In this example, as neither the END IF nor the FORMAT is a single executable statement, the CONTINUE statement (which does nothing) is used simply in order for there to be some statement to denote as the final statement of the loop.
EXP() corresponds to the exponential function . In FORTRAN 77, this is a generic function, meaning that it accepts arguments of multiple types (such as REAL and, in this example, COMPLEX). In FORTRAN 66, a specific function would have to be called by name depending on the type of the function arguments (for this example, CEXP() for a COMPLEX-valued argument).
COMPLEX-valued argument, REAL() and AIMAG() return the values of the argument's real and imaginary components, respectively.
FORMAT statement.
Incidentally, the output of the above program is as follows (see the article on Euler's formula for the geometric interpretation of these values as eight points spaced evenly about a unit circle in the complex plane).
mac:~/Desktop $ cmplxd e**(j*0*pi/4) = 1.0000000 + j0.0000000 e**(j*1*pi/4) = 0.7071068 + j0.7071068 e**(j*2*pi/4) = 0.0000000 + j1.0000000 e**(j*3*pi/4) = -0.7071068 + j0.7071068 e**(j*4*pi/4) = -1.0000000 - j0.0000001 e**(j*5*pi/4) = -0.7071066 - j0.7071069 e**(j*6*pi/4) = 0.0000000 - j1.0000000 e**(j*7*pi/4) = 0.7071070 - j0.7071065Error can be seen occurring in the last decimal place in some of the numbers above, a result of the
COMPLEX data type representing its real and imaginary components in single precision. Incidentally, Fortran 90 also introduced a double-precision complex-number data type.
program cylinderCalculate the surface area of a cylinder. Declare variables and constants. constants=pi variables=radius squared and height implicit none ! Require all variables to be explicitly declared
integer :: ierr character :: yn real :: radius, height, area real, parameter :: pi = 3.1415926536
interactive_loop: do
Prompt the user for radius and height and read them. write (*,*) 'Enter radius and height.' read (*,*,iostat=ierr) radius,height
If radius and height could not be read from input, then cycle through the loop. if (ierr /= 0) then write(*,*) 'Error, invalid input.' cycle interactive_loop end if
Compute area. The ** means "raise to a power." area = 2 * pi * (radius**2 + radius*height)
Write the input variables (radius, height) and output (area) to the screen. write (*,'(1x,a7,f6.2,5x,a7,f6.2,5x,a5,f6.2)') & 'radius=',radius,'height=',height,'area=',area
yn = ' ' yn_loop: do write(*,*) 'Perform another calculation? y*' read(*,'(a1)') yn if (yn
'y' .or. yn
'Y') exit yn_loop if (yn'n' .or. yn
'N' .or. yn==' ') exit interactive_loop end do yn_loopend do interactive_loop
end program cylinder
DO loops and IF/THEN statements in manipulating the array; mathematical operations are applied to the array as a whole. Also apparent is the use of descriptive variable names and general code formatting that comport with contemporary programming style. This example computes an average over data entered interactively.
program averageread in some numbers and take the average As written, if there are no data points (or no positive/negative points) an average of zero is returned. While this may not be desired behavior, it keeps this example simple. implicit none integer :: NumberOfPoints real, dimension(:), allocatable :: Points real :: AveragePoints=0., PositiveAverage=0., NegativeAverage=0.
write (*,*) 'Input number of points to average:' read (*,*) NumberOfPoints
allocate (Points(NumberOfPoints))
write (*,*) 'Enter the Points to average:' read (*,*) Points
take the average by summing Points and dividing by NumberOfPoints if (NumberOfPoints>0) AveragePoints = sum(Points)/NumberOfPointsnow form average over positive and negative points only if (count(Points>0.)>0) PositiveAverage = sum(Points, Points>0.)/count(Points>0.) if (count(Points<0.)>0) NegativeAverage = sum(Points, Points<0.)/count(Points<0.)deallocate (Points)
print result to terminal write (*,'(Average = , 1g12.4)') AveragePoints write (*,'(Average of positive points = , 1g12.4)') PositiveAverage write (*,'(Average of negative points = , 1g12.4)') NegativeAverageend program average
function GaussSparse(NumIter, Tol, b, A, X, ActualIter)This function solves a system of equations (Ax = b) by using the Gauss-Jordan Method implicit none
real GaussSparse
Input: its value cannot be modified from within the function integer, intent(in) :: NumIter real, intent(in) :: Tol real, intent(in), dimension(1:) :: b real, intent(in), dimension(1:,1:) :: AInput/Output: its input value is used within the function, and can be modified real, intent(inout), dimension(1:) :: XOutput: its value is modified from within the function, only if the argument is required integer, optional, intent(out) :: ActualIterLocals integer i, n, Iter real TolMax, XkInitialize values n = ubound(b, dim = 1) ! Size of array, obtained using ubound intrinsic function TolMax = 2. * Tol Iter = 0Compute solution until convergence convergence_loop: do while (TolMax >= Tol.AND.Iter < NumIter); Iter = Iter + 1TolMax = -1. ! Reset the tolerance value
Compute solution for the k-th iteration iteration_loop: do i = 1, nCompute the current x-value Xk = (b(i) - sum(A(i,1:i-1) * X(1:i-1)) - sum(A(i,i+1:n) * X(i+1:n))) / A(i, i)Compute the error of the solution TolMax = max((abs(X(i) - Xk)/(1. + abs(Xk))) ** 2, abs(A(i, i) * (X(i) - Xk)), TolMax) X(i) = Xk enddo iteration_loop enddo convergence_loopif (present(ActualIter)) ActualIter = Iter GaussSparse = TolMax
end function GaussSparse
Note that an explicit interface to this routine must be available to its caller so that the type signature is known. This is preferably done by placing the function in a MODULE and then USEing the module in the calling routine. An alternative is to use an INTERFACE block.
subroutine Swap_Real(a1, a2)implicit none
Input/Output real, intent(inout) :: a1(:), a2(:)Locals integer :: lb(1), & !Lower bound ub(1) !Upper bound integer i real aGet bounds lb = lbound(a1) ub = ubound(a1)Swap do i = lb(1), ub(1) a = a1(i) a1(i) = a2(i) a2(i) = a enddoend subroutine Swap_Real
As in the previous example, an explicit interface to this routine must be available to its caller so that the type signature is known. As before, this is preferably done by placing the function in a MODULE and then USEing the module in the calling routine. An alternative is to use a INTERFACE block.
Fortran 90 pointers are "associated" with well-defined "target" variables, via either the pointer assignment operator (=>) or an ALLOCATE statement. When appearing in expressions, pointers are always dereferenced; no "pointer arithmetic" is possible.
The following example illustrates the concept:
program TestNOTE: Variable expressions in format statements (e.g., or ) are compiler-dependent. Also, array notation (e.g., *) is a Fortran 2003 feature; for Fortran 95, use (/1,2,3/) instead. use FunctionsModule, only: DoSomething => A !This function performs some !operation on the integer !input and returns its result implicit none
integer, parameter :: m = 3, n = 3 integer, pointer :: p(:)=>null(), q(:,:)=>null() integer, allocatable, target :: A(:,:) integer ios = 0
allocate(A(1:m, 1:n), q(1:m, 1:n), stat = ios) if (ios /= 0) stop 'Error during allocation of A and q'
Assign the matrix A = 4 7 5 8 6 9] A = reshape(i = 1, m*n), n) q = Ap will be associated with the first column of A p => A(:, 1)This operation on p has a direct effect on matrix A p = p ** 2This will end the association between p and the first column of A nullify(p)Matrix A becomes: A = 4 7 5 8 6 9 ] write(*, '(/, "Matrix A becomes:",/,"A = ("[",(i1,2x),"" target="_blank" >* ",/,5x)"]")') & ((A(i, j), j = 1, n), i = 1, m)Perform some array operation q = q + AMatrix q becomes: q = 2 8 14 6 10 16 12 18 ] write(*, '(/, "Matrix q becomes:",/,"q = ("[",(i2,2x),"" target="_blank" >* ",/,5x)"]")') & ((q(i, j), j = 1, n), i = 1, m)Use p as an ordinary array allocate (p(1:m*n), stat = ios) if (ios /= 0) stop 'Error during allocation of p'Perform some array operation p = j) + A(i, j) ** 2), i = 1, m), j = 1, n)write(*, '(
(i1,4x,"p* = ",i5))') (i, p(i), i = 1, m * n) deallocate(A, p, q, stat = ios) if (ios /= 0) stop 'Error during deallocation'
end program Test
CONTAINed procedures. Unlike a simple INCLUDE file, a module is an independent program unit that can be compiled separately and linked in its binary form. Once compiled, a module's public contents can be made visible to a calling routine via the USE statement.
The module mechanism makes the explicit interface of procedures easily available to calling routines. In fact, modern Fortran encourages every SUBROUTINE and FUNCTION to be CONTAINed in a MODULE. This allows the programmer to use the newer argument passing options, and allows the compiler to perform full type checking on the interface.
The following example also illustrates derived types and overloading of procedures and operators.
module GlobalModuleReference to a pair of procedures included in a previously compiled module named PortabilityLibrary use PortabilityLibrary, only: GetLastError, & ! Generic procedure Date ! Specific procedureConstants integer, parameter :: dp_k = kind (1.0d0) ! Double precision kind real, parameter :: zero = (0.) real(dp_k), parameter :: pi = 3.14159265358979_dp_kVariables integer :: n, m, retint logical :: status, retlog character(50) :: AppNameArrays real, allocatable, dimension(:,:,:) :: a, b, c, d complex(dp_k), allocatable, dimension(:) :: zDerived type definitions type ijk integer i integer j integer k end type ijktype matrix integer m, n real, allocatable :: a(:,:) ! Fortran 2003 feature. For Fortran 95, ! use the pointer attribute instead end type matrix
All the variables and procedures from this module can be accessed by other program units, except for AppName public private AppNameProcedure overloading interface swap module procedure swap_Integer, swap_Real end interface swapinterface GetLastError ! This adds a new, additional procedure to the ! generic procedure GetLastError module procedure GetLastError_GlobalModule end interface GetLastError
Operator overloading interface operator(+) module procedure add_ijk end interfacePrototype for external procedure interface real function GaussSparse(NumIter, Tol, b, A, X) integer, intent(in) :: NumIter real, intent(in) :: Tol real, intent(in), dimension(1:) :: b real, intent(in), dimension(1:,1:) :: A real, intent(inout), dimension(1:) :: X end function GaussSparse end interfaceProcedures included in the module containsInternal function function add_ijk(ijk_1, ijk_2) type(ijk) add_ijk, ijk_1, ijk_2 intent(in) :: ijk_1, ijk_2 add_ijk = ijk(ijk_1%i + ijk_2%i, ijk_1%j + ijk_2%j, ijk_1%k + ijk_2%k) end function add_ijkInclude external files include 'Swap_Integer.f90' ! Comments SHOULDN'T be added on include lines include 'Swap_Real.f90' end module GlobalModule
PARAMETER statement (the preferred method of defining constants), the DATA statement was the conventional way to define constants, although this statement merely specified initial values and did not prevent the corresponding variables from being modified (as by regular assignment statements). It should be noted that the "best" value of pi in a program does indeed change if one moves the program to a computer with a different number of bits per word. For that reason, it is recommended to assign PI as PI = ACOS(-1.) or PI = 4.*ATAN(1.), which are portable ways of writing PI to maximum precision. (There is no round-off error when multiplying a REAL by 4 because it simply increases the power of 2 exponent for the number.)
Array programming languages | Imperative programming languages | Programming languages | Numerical programming languages | Object-oriented programming languages | Procedural programming languages | ANSI standards | ISO standards | IEC standards
فورتران | FORTRAN | Fortran | Fortran | Fortran | Fortran | FORTRAN | Fortran | Fortran (programlingvo) | Fortran | 포트란 | Fortran | Fortran | FORTRAN | Fortran | FORTRAN | Fortran | Fortran | Fortran | FORTRAN | Fortran | Fortran | Fortran | Fortran | Fortran | Фортран | Fortran | Fortran | FORTRAN | Fortran | Fortran | ภาษาฟอร์แทรน | Fortran | FORTRAN | Fortran | Fortran (мова програмування)