This document describes those parts of the Fortran 2008 language which are not in Fortran 2003. These are all supported by the latest release of the NAG Fortran Compiler.
The compiler release in which a feature was made available is indicated by square brackets; for example, a feature marked as ‘[5.3]’ was first available in Release 5.3.
Fortran 2008 is a major revision to Fortran 2003: the new language features can be grouped as follows:
Release 6.2 of the NAG Fortran Compiler limited execution to a single image, with no parallel execution. Release 7.0 of the NAG Fortran Compiler can execute multiple images in parallel on SMP machines, using Co-SMP technology.
NUM_IMAGES()returns the number of images. Each image has an “image index”; this is a positive integer from 1 to the number of images. The intrinsic function
THIS_IMAGE()returns the image index of the executing image.
SAVEattribute or be a dummy argument.
A coarray has a “corank”, which is the number of “codimensions” it has.
Each codimension has a lower “cobound” and an upper cobound, determining the “coshape”.
The upper cobound of the last codimension is “
*”; rather like an assumed-size array.
The “cosubscripts” determine the image index of the reference, in the same way that the
subscripts of an array determine the array element number.
Again, like an assumed-size array, the image index must be less than or equal to the number of images.
A coarray can be a scalar or an array.
It cannot have the
POINTER attribute, but it can have pointer components.
As well as variables, coarray components are possible.
In this case, the component must be an
ALLOCATABLE coarray, and any variable with such a
component must be a dummy argument or have the
CODIMENSIONattribute or statement. For example,
REAL a[100,*] REAL,CODIMENSION[-10:10,-10:*] :: b CODIMENSION c[*]declares the coarray
Ato have corank 2 with lower “cobounds” both 1 and the first upper cobound 100, the coarray
Bto have corank 2 with lower cobounds both −10 and the first upper cobound 10, and the coarray
Cto have corank 1 and lower cobound 1. Note that for non-allocatable coarrays, the coarray-spec must always declare the last upper cobound with an asterisk, as this will vary depending on the number of images.
ALLOCATABLE coarray is declared with a deferred-coshape-spec, for example,
REAL,ALLOCATABLE :: d[:,:,:,:]declares the coarray
Dto have corank 4.
REAL,SAVE :: e[*]the coindexed object
erefers to the copy of
Eon image 1, and
erefers to the copy of
Eon image 13. For a more complicated example: given
REAL,SAVE :: f[10,21:30,0:*]the reference
f[3,22,1]refers to the copy of
Fon image 113. There is no correlation between image numbers and any topology of the computer, so it is probably best to avoid complicated codimensions, especially if different coarrays have different coshape.
When a coarray is an array, you cannot put the cosubscripts directly after the array name, but must use array section notation instead. For example, with
REAL,SAVE :: g(10,10)[*]the reference
g[inum]is invalid, to refer to the whole array
INUMyou need to use
Similarly, to access a single element of
G, the cosubscripts follow the subscripts, e.g.
Finally, note that when a coarray is accessed, whether by its own image or remotely, the segment ordering rules (see next section) must be obeyed. This is to avoid nonsense answers from data races.
If a coarray is defined (assigned a value) in a segment on image I, another image J is only allowed to reference or define it in a segment that follows the segment on I.
The image control statements, and their synchronisation effects, are as follows.
SYNC ALLstatement executions on other images; the segment following the nth execution of a
SYNC ALLstatement on one image follows all the segments that preceded the nth execution of a
SYNC ALLstatement on every other image.
SYNC IMAGES (list
SYNC IMAGESstatement executions on the images in list, which is an integer expression that may be scalar or a vector. Including the invoking image number in list has no effect. The segment following the nth execution of a
SYNC IMAGESstatement on image I with the image number J in its list follows the segments on image J before its nth execution of
SYNC IMAGESwith I in its list.
SYNC IMAGES (*)
SYNC IMAGESwith every image no. in its list, e.g.
SYNC IMAGES ([(i,i=1,NUM_IMAGES())]).
CRITICALconstruct at a time. The code inside a
CRITICALconstruct forms a segment, which follows the previous execution (on whatever image) of the
LOCKstatements that locks a particular lock variable follows the
UNLOCKstatement that previously unlocked the variable.
END FUNCTION, or
END SUBROUTINEstatement that causes automatic deallocation of a local
ALLOCATABLEcoarray, synchronises with all images (which must execute the same
MOVE_ALLOCwith coarray arguments synchronises all images, which must execute the same
Note that image control statements have side-effects, and therefore are not permitted in
pure procedures or within
DO CONCURRENT constructs.
ALLOCATABLEcoarray, you must give the desired cobounds in the
ALLOCATEstatement. For example,
REAL,ALLOCATABLE :: x(:,:,:)[:,:] ... ALLOCATE(x(100,100,3)[1:10,*])Note that the last upper cobound must be an asterisk, the same as when declaring an explicit-coshape coarray.
When allocating a coarray there is a synchronisation: all images must execute the same
ALLOCATE statement, and all the bounds, type parameters, and cobounds of the coarray
must be the same on all images.
Similarly, there is a synchronisation when a coarray is deallocated, whether by a
statement or automatic deallocation by an
END statement; every image must execute the
Note that the usual automatic reallocation of allocatable variables in an intrinsic assignment statement, e.g. when the expression is an array of a different shape, is not available for coarrays. An allocatable coarray variable being assigned to must already be allocated and be conformable with the expression; furthermore, if it has deferred type parameters they must have the same values, and if it is polymorphic it must have the same dynamic type.
CRITICALconstruct provides a mechanism for ensuring that only one image at a time executes a code segment. For example,
CRITICAL ...do something END CRITICALIf an image I arrives at the CRITICAL statement while another image J is executing the block of the construct, it will wait until image J has executed the
END CRITICALstatement before continuing. Thus the
END CRITICALsegment on image I follows the equivalent segment on image J.
As a construct, this may have a name, e.g.
critsec: CRITICAL ... END CRITICAL critsecThe name has no effect on the operation of the construct. Each
CRITICALconstruct is separate from all others, and has no effect on their execution.
LOCK_TYPE, defined in the intrinsic module
ISO_FORTRAN_ENV. A lock variable must be a coarray, or a component of a coarray. It is initially “unlocked”; it is locked by execution of a
LOCKstatement, and unlocked by execution of an
UNLOCKstatement. Apart from those statements, it cannot appear in any variable definition context, other than as the actual argument for an
Execution of the segment after a
LOCK statement successfully locks the variable
follows execution of the segment before the
UNLOCK statement on the image that unlocked it.
INTEGER FUNCTION get_sequence_number() USE iso_fortran_env INTEGER :: number = 0 TYPE(lock_type) lock[*] LOCK(lock) number = number + 1 get_sequence_number = number UNLOCK(lock) END FUNCTIONIf the variable
lockon image 1 is locked when the
LOCKstatement is executed, it will wait for it to become unlocked before continuing. Thus the function
get_sequence_number()provides an one-sided ordering relation: the segment following a call that returned the value N will follow every segment that preceded a call that returned a value less than N.
Conditional locking is provided with the
specifier; if this specifier is present, the executing image only acquires the lock if it was
previously unlocked. For example,
LOGICAL gotit LOCK(lock,ACQUIRED_LOCK=gotit) IF (gotit) THEN ! We have the lock. ELSE ! We do not have the lock - some other image does. END IF
It is an error for an image to try to
LOCK a variable that is already locked to that image,
UNLOCK a variable that is already unlocked, or that is locked to another image.
STAT= specifier is used, these errors will return the values
(these named constants are provided by the intrinsic module
ATOMIC_INT_KINDor a logical of kind
ATOMIC_LOGICAL_KIND(these named constants are provided by the intrinsic module
ISO_FORTRAN_ENV), can be defined with the intrinsic subroutine
ATOMIC_DEFINE, or referenced by the intrinsic subroutine
ATOMIC_REF. For example,
MODULE stopping USE iso_fortran_env LOGICAL(atomic_logical_kind),PRIVATE :: stop_flag[*] = .FALSE. CONTAINS SUBROUTINE make_it_stop CALL atomic_define(stop_flag,.TRUE._atomic_logical_kind) END SUBROUTINE LOGICAL FUNCTION please_stop() CALL atomic_ref(please_stop,stop_flag) END FUNCTION END MODULEIn this example, it is perfectly valid for any image to call
make_it_stop, and for any other image to invoke the function
please_stop(), without any regard for segments. (On a distributed memory machine it might take some time for changes to the atomic variable to be visible on other images, but they should eventually get the message.)
Note that ordinary assignment and referencing should not be mixed with calls to the atomic subroutines, as ordinary assignment and referencing are always subject to the segment ordering rules.
STOPstatement, or the
END PROGRAMstatement, normal termination is initiated. The other images continue execution, and all data on the “stopped” image remains; other images can continue to reference and define coarrays on the stopped image.
When normal termination has been initiated on all images, the program terminates.
ERR=specifier, the entire program is error terminated. On a distributed memory machine it may take some time for the error termination messages to reach every image, so the termination might not be immediate.
ERROR STOP statement initiates error termination.
FAIL IMAGEstatement causes the executing image to fail (stop responding to accesses from other images). These extensions are listed in the detailed syntax below, even though they are not part of the Fortran 2008 standard.
FAIL IMAGE statement itself is not very useful when the number of images is equal to one,
as it inevitably causes complete program failure.
In a data object designator, a part (component or base object) that is a coarray can include an
) ] [ image-selector ]
left-bracket cosubscript-list [
, image-selector-spec ] right-bracket
STAT = scalar-int-variable
TEAM = team-value
TEAM_NUMBER = scalar-int-expression
TEAM_TYPEfrom the intrinsic module
STAT=variable is assigned zero if the reference or definition was successful, and the value
STAT_FAILEDif the image referenced has failed.
( [ sync-stat-list ]
END CRITICAL [ construct-name ]
ERRMSG=specifier, or both (separated by a comma). Note: The optional parentheses and sync-stat-list are Fortran 2018.
The block is not permitted to contain:
FAIL IMAGE statement:
LOCK ( lock-variable [
, lock-stat-list ]
ACQUIRED_LOCK = scalar-logical-variable
ERRMSG = scalar-default-character-variable
STAT = scalar-int-variable
LOCK_TYPEfrom the intrinsic module
SYNC ALL statement:
SYNC ALL [
( [ sync-stat-list ]
SYNC IMAGES statement:
SYNC IMAGES ( image-set [
, sync-stat-list ]
SYNC MEMORY statement:
SYNC MEMORY [
( [ sync-stat-list ]
UNLOCK ( lock-variable [
, sync-stat-list ]
SUBROUTINE ATOMIC_DEFINE(ATOM, VALUE, STAT)
LOGICAL(ATOMIC_LOGICAL_KIND), and must be a coarray or a coindexed object.
ATOMis atomically assigned the value of
VALUE, without regard to the segment rules. If
STATis present, it is assigned a positive value if an error occurs, and zero otherwise. Note:
STATis part of Fortran 2018.
SUBROUTINE ATOMIC_REF(VALUE, ATOM, STAT)
INTENT(OUT)scalar with the same type as
LOGICAL(ATOMIC_LOGICAL_KIND), and must be a coarray or a coindexed object.
ATOMis atomically read, without regard to the segment rules, and then assigned to the variable
STATis present, it is assigned a positive value if an error occurs, and zero otherwise. Note:
STATis part of Fortran 2018.
INTEGER FUNCTION IMAGE_INDEX(COARRAY, SUB)
SUBis a valid set of cosubscripts for
COARRAY, the value of the result is the image index of the image they will reference, otherwise the result has the value zero. For example, if
Xis declared with cobounds
[11:20,13:*], the result of
IMAGE_INDEX(X,[11,13])will be equal to one, and the result of
IMAGE_INDEX(x,[1,1])will be equal to zero.
FUNCTION LCOBOUND(COARRAY, DIM , KIND)
DIMappears, the result is scalar, being the value of the lower cobound of that codimension of
DIMdoes not appear, the result is a vector of length N containing all the lower cobounds of
COARRAY. The actual argument for
DIMmust not itself be an optional dummy argument.
SUBROUTINE MOVE_ALLOC(FROM, TO, STAT, ERRMSG) ! Revised
INTENT(OUT)scalar Integer with a decimal exponent range of at least four.
INTENT(INOUT)scalar default character variable.
TOare coarrays, the
CALLstatement is an image control statement that synchronises all images. If
STATis present, it is assigned a positive value if any error occurs, otherwise it is assigned the value zero. If
ERRMSGis present and an error occurs, it is assigned an explanatory message. Note: The
ERRMSGarguments are Fortran 2018.
INTEGER FUNCTION NUM_IMAGES()This intrinsic function returns the number of images. In this release of the NAG Fortran Compiler, the value will always be equal to one.
INTEGER FUNCTION THIS_IMAGE()Returns the image index of the executing image.
FUNCTION THIS_IMAGE(COARRAY)Returns an array of type Integer with default kind, with the size equal to the corank of
COARRAY, which may be a coarray of any type. The values returned are the cosubscripts for
COARRAYthat correspond to the executing image.
INTEGER FUNCTION THIS_IMAGE(COARRAY, DIM)
DIMthat corresponds to the executing image. Note: In Fortran 2008
DIMwas not permitted to be an optional dummy argument; Fortran 2018 permits that.
FUNCTION UCOBOUND(COARRAY, DIM, KIND)
DIM appears, the result is scalar, being the value of the upper cobound of that codimension of
DIM does not appear, the result is a vector of length N containing all the upper cobounds of
The actual argument for
DIM must not itself be an optional dummy argument.
Note that if
COARRAY has corank N>1, and the number of images in the current execution is not an integer multiple of the coextents up to codimension N−1, the images do not make a full rectangular pattern.
In this case, the value of the last upper cobound is the maximum value that a cosubscript can take for that codimension; e.g. with a coarray-spec of
[1:3,1:*] and four images in the execution, the last upper cobound will be equal to 2 because the cosubscripts
[1,2] are valid even though
[2,3] are not.
REAL array(2,2,2,2,2,2,2,2,2,2,2,2,2,2,2)declares a 15-dimensional array.
SELECTED_INT_KIND(18)is a valid integer kind number.
PARAMETER) that is an array can assume its shape from its defining expression; this is called an implied-shape array. The syntax is that the upper bound of every dimension must be an asterisk, for example
REAL,PARAMETER :: idmat3(*,*) = Reshape( [ 1,0,0,0,1,0,0,0,1 ], [ 3,3 ] ) REAL,PARAMETER :: yeardata(2000:*) = [ 1,2,3,4,5,6,7,8,9 ]declares
idmat3to have the bounds
yeardatato have the bounds
TYPEkeyword can be used to declare entities of intrinsic type, simply by putting the intrinsic type-spec within the parentheses. For example,
TYPE(REAL) x TYPE(COMPLEX(KIND(0d0))) y TYPE(CHARACTER(LEN=80)) zis completely equivalent, apart from being more confusing, to
REAL x COMPLEX(KIND(0d0)) y CHARACTER(LEN=80) z
PROCEDURE,NOPASS :: a PROCEDURE,NOPASS :: b=>x PROCEDURE,NOPASS :: cthe single statement
PROCEDURE,NOPASS :: a, b=>x, cwill suffice.
C_ASSOCIATED, 7.0 for
C_FUNLOC] A specification expression may now use the
C_FUNLOCfunctions from the
ISO_C_BINDINGmodule. For example, given a
TYPE(C_PTR)variable X and another interoperable variable
INTEGER workspace(MERGE(10,20,C_ASSOCIATED(X,C_LOC(Y))))is allowed, and will give
workspacea size of 10 elements if the C pointer
Xis associated with
Y, and 20 elements otherwise.
INTERFACE OPERATOR(.user.) PURE INTEGER FUNCTION userfun(x) REAL,INTENT(IN) :: x END FUNCTION END INTERFACEthe user-defined operator
.user.may be used in a specification expression as follows:
Note that this applies to overloaded intrinsic operators as well as user-defined operators.
Type t2 Type(t),Pointer :: p Type(t),Allocatable :: a End Type Type t Integer c End Type
An allocatable component can also be of recursive type, or two types can be mutually recursive. For example,
Type t Integer v Type(t),Allocatable :: a End TypeThis allows lists and trees to be built using allocatable components. Building or traversing such data structures will usually require recursive procedure calls, as there is no allocatable analogue of pointer assignment.
No matter how deeply nested such recursive data structures become, they can never be circular (again, because there is no pointer assignment). As usual, deallocating the top object of such a structure will recursively deallocate all its allocatable components.
LEN) when the enquiry is not about a deferred characteristic.
For example, in
Elemental Subroutine s(x,n,y) Real,Intent(In) :: x Integer,Intent(In) :: n Real,Intent(Out) :: y Real temp(n) ...the dummy argument
Ncan be used to declare the local array
SAVEattribute (variables in modules and the main program have this attribute implicitly). For procedure pointers, the target must be a module procedure or external procedure, not a dummy procedure, internal procedure, or statement function.
Module m Real,Target :: x Real,Pointer :: p => x End Module Program test Use m p = 3 Print *,x ! Will print the value 3.0 End Program
Module m Real,Target :: x Type t Real,Pointer :: p => x End Type End Module Program test Use m Type(t) y y%p = 3 Print *,x ! Will print the value 3.0 End Program
Module m Real,Target :: x Type t Real,Pointer :: p End Type End Module Program test Use m Type(t) :: y = t(x) y%p = 3 Print *,x ! Will print the value 3.0 End Program
INTENT(INOUT)dummy argument, and as the selector in an
SELECT TYPEconstruct that modifies the associate-name.
For example, with this module,
Module m Real,Target,Save :: table(100) = 0 Contains Function f(n) Integer,Intent(In) :: n Real,Pointer :: f f => table(Min(Max(1,n),Size(table))) End Function End Modulethe program below will print “
Program example Use m f(13) = -123 Print 1,f(13) 1 Format(ES10.3) End Program
It should be noted that the syntax of a statement function definition is identical to part of the syntax of a pointer function reference as a variable; the existence of a pointer-valued function that is accessible in the scope determines which of these it is. This may lead to confusing error messages in some situations.
With the above module, this program demonstrates the use of the feature with an
Program assoc_eg Use m Associate(x=>f(3), y=>f(4)) x = 0.5 y = 3/x End Associate Print 1,table(3:4) ! Will print " 5.00E-01 6.00E+00" 1 Format(2ES10.2) End Program
Finally, here is an example using argument passing.
Program argument_eg Use m Call set(f(7)) Print 1,table(7) ! Will print "1.41421" 1 Format(F7.5) Contains Subroutine set(x) Real,Intent(Out) :: x x = Sqrt(2.0) End Subroutine End Program
Other contexts where a reference to a pointer-valued function may be used instead of a variable designator include:
WRITEstatement (the function must return a pointer to a character string or array for this);
ERRMSG=variable in an
DEALLOCATEstatement, or in an image control statement such as
Module ppfun Private Abstract Interface Subroutine charsub(string) Character(*),Intent(In) :: string End Subroutine End Interface Public charsub,hello_goodbye Contains Subroutine hello(string) Character(*),Intent(In) :: string Print *,'Hello: ',string End Subroutine Subroutine bye(string) Character(*),Intent(In) :: string Print *,'Goodbye: ',string Stop End Subroutine Function hello_goodbye(flag) Logical,Intent(In) :: flag Procedure(hello),Pointer :: hello_goodbye If (flag) Then hello_goodbye => hello Else hello_goodbye => bye End If End Function End Module Program example Use ppfun Procedure(charsub),Pointer :: pp pp => hello_goodbye(.True.) Call pp('One') pp => hello_goodbye(.False.) Call pp('Two') End ProgramThe function
ppfunreturns a pointer to a procedure, which needs to be pointer-assigned to a procedure pointer to be invoked. When executed, this example will print
Hello: One Goodbye: Two
Use of this feature is not recommended, as it blurs the lines between data objects and procedures; this may lead to confusion or misunderstandings during code maintenance. The feature provides no functionality that was not already provided by procedure pointer components.
MOLD=is present and its expression is an array, the array can take its shape directly from the expression. This is a lot more concise than using
UBOUND, especially for a multi-dimensional array.
SUBROUTINE s(x,mask) REAL x(:,:,:) LOGICAL mask(:,:,:) REAL,ALLOCATABLE :: y(:,:,:) ALLOCATE(y,MOLD=x) WHERE (mask) y = 1/x ELSEWHERE y = HUGE(x) END WHERE ! ... END SUBROUTINE
ALLOCATEstatement with the
SOURCE=clause is permitted to have more than one allocation. The source-expr is assigned to every variable allocated in the statement. For example,
PROGRAM multi_alloc INTEGER,ALLOCATABLE :: x(:),y(:,:) ALLOCATE(x(3),y(2,4),SOURCE=42) PRINT *,x,y END PROGRAMwill print the value “42” eleven times (the three elements of
xand the eight elements of
y). If the source-expr is an array, every allocation needs to have the same shape.
COMPLEXobject can be accessed using the complex part designators ‘
%RE’ and ‘
%IM’. For example, given
COMPLEX,PARAMETER :: c = (1,2), ca(2) = [ (3,4),(5,6) ]the designators
c%imhave the values 1 and 2 respectively, and
ca%imare arrays with the values
[ 3,5 ]and
[ 4,6 ]respectively. In the case of variables, for example
COMPLEX :: v, va(10)the real and imaginary parts can also be assigned to directly; the statement
va%im = 0will set the imaginary part of each element of
vato zero without affecting the real part.
ALLOCATEstatement for one or more variables, the
MOLD=clause can be used to give the variable(s) the dynamic type and type parameters (and optionally shape) of an expression. The expression in
MOLD=must be type-compatible with each allocate-object, and if the expression is a variable (e.g.
MOLD=X), the variable need not be defined. Note that the
MOLD=clause may appear even if the type, type parameters and shape of the variable(s) being allocated are not mutable. For example,
CLASS(*),POINTER :: a,b,c ALLOCATE(a,b,c,MOLD=125)will allocate the unlimited polymorphic pointers
Cto be of type Integer (with default kind); unlike
SOURCE=, the values of
Cwill be undefined.
)works. For example, given
CLASS(*),ALLOCATABLE :: xexecution of the assignment statement
x = 43will result in
Xhaving dynamic type Integer (with default kind) and value 43, regardless of whether
Xwas previously unallocated or allocated with any other type (or kind).
REAL,TARGET :: x(100,100) REAL,POINTER :: x1(:) x1(1:Size(x)) => xestablishes
X1as a single-dimensional alias for the whole of
BLOCKconstruct allows declarations of entities within executable code. For example,
Do i=1,n Block Real tmp tmp = a(i)**3 If (tmp>b(i)) b(i) = tmp End Block End DoHere the variable
tmphas its scope limited to the
BLOCKconstruct, so will not affect anything outside it. This is particularly useful when including code by
INCLUDEor by macro preprocessing.
All declarations are allowed within a
BLOCK construct except for
VALUE; also, statement function
definitions are not permitted.
BLOCK constructs may be nested; like other constructs, branches into a
BLOCK construct from outside are not permitted.
A branch out of a
BLOCK construct “completes” execution of the
Entities within a
BLOCK construct that do not have the
attribute (including implicitly via initialisation), will cease to exist when
execution of the construct is completed.
For example, an allocated
ALLOCATABLE variable will be automatically
deallocated, and a variable with a
FINAL procedure will be finalised.
EXITstatement is no longer restricted to exiting from a
DOconstruct; it can now be used to jump to the end of a named
SELECT TYPEconstruct (i.e. any named construct except
WHERE). Note that an
EXITstatement with no construct-name still exits from the innermost
DOconstruct, disregarding any other named constructs it might be within.
STOPstatement, the stop-code may be any scalar constant expression of type integer or default character. (In the NAG Fortran Compiler this also applies to the
PAUSEstatement, but that statement is no longer standard Fortran.) Additionally, the
STOPstatement with an integer stop-code now returns that value as the process exit status (on most operating systems there are limits on the value that can be returned, so for the NAG Fortran Compiler this returns only the lower eight bits of the value).
ERROR STOPstatement has been added. This is similar to the
STOPstatement, but causes error termination rather than normal termination. The syntax is identical to that of the
STOPstatement apart from the extra keyword ‘
ERROR’ at the beginning. Also, the default process exit status is zero for normal termination, and non-zero for error termination.
IF (x<=0) ERROR STOP 'x must be positive'
FORALLconstruct now has an optional type specifier in the initial statement of the construct, which can be used to specify the type (which must be
INTEGER) and kind of the index variables. When this is specified, the existence or otherwise of any entity in the outer scope that has the same name as an index variable does not affect the index variable in any way. For example,
Complex i(100) Real x(200) ... Forall (Integer :: i=1:Size(x)) x(i) = i
Note that the
FORALL construct is still not recommended for high performance,
as the semantics imply evaluating the right-hand sides into array temps the
size of the iteration space, and then assigning to the variables; this usually
performs worse than ordinary
DO CONCURRENTconstruct is a
DOloop with restrictions and semantics intended to allow efficient execution. The iterations of a
DO CONCURRENTconstruct may be executed in any order, and possibly even in parallel. The loop index variables are local to the construct.
DO CONCURRENT header has similar syntax to the
including the ability to explicitly specify the type and kind of the loop index
variables, and including the scalar mask.
The restrictions on the
DO CONCURRENT construct are:
ERROR STOPis allowed);
EXITstatement cannot be used to terminate the loop;
CYCLEstatement cannot refer to an outer loop;
Integer vsub(n) ... Do Concurrent (i=1:n) ! Safe because vsub has no duplicate values. x(vsub(i)) = i End Do
The full syntax of the
DO CONCURRENT statement is:
DO [ label ] [
( [ integer-type-spec
:: ] triplet-spec [
, triplet-spec ]... [
, mask-expr ]
name = expr : expr [ : expr ]
ATANHcompute the inverse hyperbolic cosine, sine or tangent respectively. There is a single argument
X, which may be of type Real or Complex; the result of the function has the same type and kind. When the argument is Complex, the imaginary part is expressed in radians and lies in the range 0≤im≤π for the
ACOSHfunction, and −π/2≤im≤π/2 for the
ATANH(0.7615942) are all approximately equal to
BESSEL_Y1compute the Bessel functions J0, Y0, J1 and Y1 respectively. These functions are solutions to Bessel's differential equation. The J functions are of the 1st kind and the Y functions are of the 2nd kind; the following subscript indicates the order (0 or 1). There is a single argument
X, which must be of type Real; the result of the function has the same type and kind. For functions of the 2nd kind (
BESSEL_Y1), the argument
Xmust be positive. For example,
BESSEL_YNcompute the Bessel functions Jn and Yn respectively. These functions come in two forms: an elemental form and a transformational form.
The elemental form has two arguments:
N, the order of the function to
X, the argument of the Bessel function.
BESSEL_JN(0,X) is identical to
The transformational form has three scalar arguments:
The result is a vector of size
approximations to the Bessel functions of orders
BESSEL_JN(5,7.5) is approximately
BESSEL_YN(5,7.5) is approximately
BESSEL_JN(3,5,7.5) is approximately
[ -0.258061, 0.023825, 0.283474 ] and
BESSEL_YN(3,5,7.5) is approximately
[ 0.159708, 0.314180, 0.175418 ].
ERFC_SCALEDcompute the error function, the complementary error function and the scaled complementary error function, respectively. The single argument
Xmust be of type real.
The error function is the integral of
from 0 to
SQRT(π); this rapidly converges to 1.
The complementary error function is 1 minus the error function, and fairly
quickly converges to zero.
The scaled complementary error function scales the value (of 1 minus the error
X**2); this also converges to zero but only very
LOG_GAMMAcompute the gamma function and the natural logarithm of the absolute value of the gamma function respectively. The single argument
Xmust be of type real, and must not be zero or a negative integer.
The gamma function is the extension of factorial from the integers to the
reals; for positive integers,
GAMMA(X) is equal to (
i.e. factorial of
This grows very rapidly and thus overflows for quite small
LOG_GAMMA also diverges but much more slowly.
HYPOTcomputes the “Euclidean distance function” (square root of the sum of squares) of its arguments
Ywithout overflow or underflow for very large or small
Y(unless the result itself overflows or underflows). The arguments must be of type Real with the same kind, and the result is of type Real with that kind. Note that
HYPOT(X,Y)is semantically and numerically equal to
HYPOT(3e30,4e30) is approximately equal to
NORM2(X,DIM)reduces Real arrays using the L2-norm operation. This operates exactly the same as
PRODUCT, except for the operation involved. The L2 norm of an array is the square root of the sum of the squares of the elements. Note that unlike most of the other reduction functions,
NORM2does not have a
DIMargument is optional; an actual argument for
DIMis not itself permitted to be an optional dummy argument.
The calculation of the result value is done in such a way as to avoid
intermediate overflow and underflow, except when the result itself is outside
the maximum range.
NORM2([X,Y]) is approximately the same as
BLTperform bitwise (i.e. unsigned) comparisons. They each have two arguments,
J, which must be of type Integer but may be of different kind. The result is default Logical.
BGE(INT(Z'FF',INT8),128) is true, while
INT(Z'FF',INT8)>=128 is false.
DSHIFTRperform double-width shifting. They each have three arguments,
SHIFTwhich must be of type Integer, except that one of
Jmay be a BOZ literal constant – it will be converted to the type and kind of the other
Jmust have the same kind if they are both of type Integer. The result is of type Integer, with the same kind as
Jarguments are effectively concatenated to form a single double-width value, which is shifted left or right by
DSHIFTLthe result is the top half of the combined shift, and for
DSHIFTRthe result is the bottom half of the combined shift.
DSHIFTL(INT(B'11000101',1),B'11001001',2) has the value
INT(B'00010111',1) (decimal value 23), whereas
DSHIFTR(INT(B'11000101',1),B'11001001',2) has the value
INT(B'01110010',1) (decimal value 114).
IPARITYreduce arrays using bitwise operations. These are exactly the same as
PRODUCT, except that instead of reducing the array by the
*operation, they reduce it by the
IEORintrinsic functions respectively. That it, each element of the result is the bitwise-and, bitwise-or, or bitwise-exclusive-or of the reduced elements. If the number of reduced elements is zero, the result is zero for
TRAILZreturn the number of leading (most significant) and trailing (least significant) zero bits in the argument
I, which must be of type Integer (of any kind). The result is default Integer.
MASKRgenerate simple left-justified and right-justified bitmasks. The value of
MASKL(I,KIND)is an integer with the specified kind that has its leftmost
Ibits set to one and the rest set to zero;
Imust be non-negative and less than or equal to the bitsize of the result. If
KINDis omitted, the result is default integer. The value of
MASKRis similar, but has its rightmost
Ibits set to one instead.
MERGE_BITS(I,J,MASK)merges the bits from Integer values
J, taking the bit from
Iwhen the corresponding bit in
1, and taking the bit from
Jwhen it is zero. All arguments must be BOZ literal constants or of type Integer, and all the Integer arguments must have the same kind; at least one of
Jmust be of type Integer, and the result has the same type and kind.
MERGE_BITS(I,J,MASK) is identical to
is equal to
INT(B'01110010') (decimal value 114).
PARITYreduces Logical arrays. It is exactly the same as
ANY, except that instead of reducing the array by the
.OR.operation, it reduces it by the
.NEQV.operation. That is, each element of the result is
.TRUE.if an odd number of reduced elements is
POPCNT(I)returns the number of bits in the Integer argument
Ithat are set to 1. The elemental intrinsic function
POPPAR(I)returns zero if the number of bits in
Ithat are set to 1 are even, and one if it is odd. The result is default Integer.
EXECUTE_COMMAND_LINEpasses a command line to the operating system's command processor for execution. It has five arguments, in order these are:
CHARACTER(*),INTENT(IN) :: COMMAND— the command to be executed;
LOGICAL,INTENT(IN),OPTIONAL :: WAIT— whether to wait for command completion (default true);
INTEGER,INTENT(INOUT),OPTIONAL :: EXITSTAT— the result value of the command;
INTEGER,INTENT(OUT),OPTIONAL :: CMDSTAT— see below;
CHARACTER(*),INTENT(INOUT),OPTIONAL :: CMDMSG— the error message if
CMDSTAT values are zero for success, −1 if command line execution is
not supported, −2 if
WAIT is present and false but asynchronous
execution is not supported, and a positive value to indicate some other error.
CMDSTAT is not present but would have been set non-zero, the program
will be terminated.
Note that Release 5.3.1 supports command line execution on all systems, and
does not support asynchronous execution on any system.
CALL EXECUTE_COMMAND_LINE('echo Hello') will probably
Hello’ in the console window.
STORAGE_SIZE(A,KIND)returns the size in bits of a scalar object with the same dynamic type and type parameters as
A, when it is stored as an array element (i.e. including any padding). The
KINDargument is optional; the result is type Integer with kind
KINDif it is present, and default kind otherwise.
A is allocatable or a pointer, it does not have to be allocated
unless it has a deferred type parameter (e.g.
CHARACTER(:)) or is
If it is a polymorphic pointer, it must not have an undefined status.
STORAGE_SIZE(13_1) is equal to 8 (bits).
IS_CONTIGUOUShas a single argument
ARRAY, which can be an array of any type. The function returns true if
ARRAYis stored contiguously, and false otherwise. Note that this question has no meaning for an array with no elements, or for an array expression since that is a value and not a variable.
FINDLOCis similar to
MINLOC, but instead of finding the location of the maximum or minimum value of an array, it finds a location that is equal to a specified value; thus it is available for all intrinsic types including
LOGICAL. It has one of the following two forms:
FINDLOC (ARRAY, VALUE, DIM, MASK, KIND, BACK ) FINDLOC (ARRAY, VALUE, MASK, KIND, BACK )where
|is an array of intrinsic type, with rank N;|
| is a scalar of the same type (if |
| operator |
| is a scalar |
| (optional) is an array of type |
| (optional) is a scalar |
| (optional) is a scalar |
The result of the function is type
KIND is present.
In the form without
DIM, the result is a vector of length N, and is the location of the element of
ARRAY that is equal to
MASK is present, only elements for which the corresponding
.TRUE. are considered.
MINLOC, the location is reported with 1 for the first element in each dimension;
if no element equal to
VALUE is found, the result is zero.
BACK is present with the value
.TRUE., the element found is the last one (in array element order);
otherwise, it is the first one.
In the form with
DIM, the result has rank N−1 (thus scalar if
ARRAY is a vector), the shape being that of
ARRAY with dimension
DIM removed, and each element of the result is the location of the (masked) element
in the dimension
DIM vector that is equal to
For example, if
ARRAY is an Integer vector with value
[ 10,20,30,40,50 ],
FINDLOC(ARRAY,30) will return the vector
[ 3 ] and
will return the vector
[ 0 ].
TANHnow accept arguments of type Complex. Note that the hyperbolic and non-hyperbolic versions of these functions and the new
ATANHfunctions are all related by simple algebraic identities, for example the new
COSH(X)is identical to the old
COS((0,1)*X)and the new
SINH(X)is identical to the old
ATANnow has an extra form
ATAN(Y,X), with exactly the same semantics as
MINLOCnow have an additional optional argument
KINDargument. It is scalar and of type Logical; if present with the value
.True., if there is more than one element that has the maximum value (for
MAXLOC) or minimum value (for
MINLOC), the array element index returned is for the last element with that value rather than the first.
For example, the value of
MAXLOC( [ 5,1,5 ], BACK=.TRUE.)is the array
[ 3 ], rather than
[ 1 ].
SELECTED_REAL_KINDnow has a third argument
RADIX; this specifies the desired radix of the Real kind requested. Note that the function
IEEE_SELECTED_REAL_KINDin the intrinsic module
IEEE_ARITHMETICalso has this new third argument, and will allow requesting IEEE decimal floating-point kinds if they become available in the future.
ISO_C_BINDINGcontains an additional procedure as follows.
INTERFACE c_sizeof PURE INTEGER(c_size_t) FUNCTION c_sizeof...(x) ! Specific name not visible TYPE(*) :: x(..) END FUNCTION END INTERFACE
The actual argument
x must be interoperable.
The result is the same as the C
sizeof operator applied to the
conceptually corresponding C entity; that is, the size of
x is an array, it is the size of the whole array,
not just one element.
x cannot be an assumed-size array.
ISO_FORTRAN_ENVcontains additional named constants as follows.
REAL128supply the kind type parameter values for integer and real kinds with the indicated bit sizes.
REAL_KINDSlist the available kind type parameter values for each type (in no particular order).
The standard intrinsic module
ISO_FORTRAN_ENV contains two new
functions as follows.
COMPILER_VERSION. This function is pure, has no arguments, and returns a scalar default character string that identifies the version of the compiler that was used to compile the source file. This function may be used in a constant expression, e.g. to initialise a variable or named constant with this information. For example,
Module version_info Use Iso_Fortran_Env Character(Len(Compiler_Version())) :: compiler = Compiler_Version() End Module Program show_version_info Use version_info Print *,compiler End ProgramWith release 6.1 of the NAG Fortran Compiler, this program will print something like
NAG Fortran Compiler Release 6.1(Tozai) Build 6105
COMPILER_OPTIONS. This function is pure, has no arguments, and returns a scalar default character string that identifies the options supplied to the compiler when the source file was compiled. This function may be used in a constant expression, e.g. to initialise a variable or named constant with this information. For example,
Module options_info Use Iso_Fortran_Env Character(Len(Compiler_Options())) :: compiler = Compiler_Options() End Module Program show_options_info Use options_info Print *,compiler End ProgramIf compiled with the options -C=array -C=pointer -O, this program will print something like
-C=array -C=pointer -O
NEWUNIT=specifier has been added to the
OPENstatement; this allocates a new unit number that cannot clash with any other logical unit (the unit number will be a special negative value). For example,
INTEGER unit OPEN(FILE='output.log',FORM='FORMATTED',NEWUNIT=unit) WRITE(unit,*) 'Logfile opened.'The
NEWUNIT=specifier can only be used if either the
FILE=specifier is also used, or if the
STATUS=specifier is used with the value
Write (*,Output_Unit) f(100)the function
fis permitted to perform i/o on any unit except
Output_Unit; for example, if the value 100 is out of range, it would be allowed to produce an error message with
Write (*,Error_Unit) 'Error in F:',n,'is out of range'
*) as its repeat count. For example,
SUBROUTINE s(x) LOGICAL x(:) PRINT 1,x 1 FORMAT('x =',*(:,' ',L1)) END SUBROUTINEwill display the entire array
xon a single line, no matter how many elements
xhas. An indefinite repeat count is only allowed at the top level of the format specification, and must be the last format item.
G0.d edit descriptors perform generalised editing with all leading and trailing blanks (except those within a character value itself) omitted. For example,
PRINT 1,1.25,.True.,"Hi !",123456789 1 FORMAT(*(G0,','))produces the output
CONTAINSstatement. In the case of the type-bound procedure part, an ineffectual
PRIVATEstatement may appear following the unnecessary
SUBROUTINE mysub(coeffs) REAL,INTENT(IN) :: coeffs(0:) ! Coefficients of polynomial. REAL integral integral = integrate(myfunc,0.0,1.0) ! Integrate from 0.0 to 1.0. PRINT *,'Integral =',integral CONTAINS REAL FUNCTION myfunc(x) RESULT(y) REAL,INTENT(IN) :: x INTEGER i y = coeffs(UBOUND(coeffs,1)) DO i=UBOUND(coeffs,1)-1,0,-1 y = y*x + coeffs(i) END DO END FUNCTION END SUBROUTINE
ALLOCATABLEdummy variable is distinguishable from a
POINTERdummy variable that does not have
IMPUREkeyword. An impure elemental procedure has the restrictions that apply to elementality (e.g. all arguments must be scalar) but does not have any of the “pure” restrictions. This means that an impure elemental procedure may have side effects and can contain input/output and
STOPstatements. For example,
Impure Elemental Integer Function checked_addition(a,b) Result(c) Integer,Intent(In) :: a,b If (a>0 .And. b>0) Then If (b>Huge(c)-a) Stop 'Positive Integer Overflow' Else If (a<0 .And. b<0) Then If ((a+Huge(c))+b<0) Stop 'Negative Integer Overflow' End If c = a + b End FunctionWhen an argument is an array, an impure elemental procedure is applied to each element in array element order (unlike a pure elemental procedure, which has no specified order). An impure elemental procedure cannot be referenced in a context that requires a procedure to be pure, e.g. within a
Impure elemental procedures are probably most useful for debugging (because i/o is allowed) and as final procedures.
VALUEattribute it does not need any
INTENTattribute. For example,
PURE SUBROUTINE s(a,b) REAL,INTENT(OUT) :: a REAL,VALUE :: b a = b END SUBROUTINE
Note however that the second argument of a defined assignment subroutine, and
all arguments of a defined operator function, are still required to have the
INTENT(IN) attribute even if they have the
SUBROUTINEkeyword on the END statement for an internal or module subprogram is now optional (when the subprogram name does not appear). Previously these keywords were only optional for external subprograms.
ENTRYstatements are regarded as obsolescent.
SUBROUTINE sub() BIND(C,NAME='one') PRINT *,'one' END SUBROUTINE SUBROUTINE sub() BIND(C,NAME='two') PRINT *,'two' END SUBROUTINE PROGRAM test INTERFACE SUBROUTINE one() BIND(C) END SUBROUTINE SUBROUTINE two() BIND(C) END SUBROUTINE END INTERFACE CALL one CALL two END PROGRAM
BIND(C)attribute, as long as it does not have a
NAME=specifier. Such a procedure is interoperable with C, but does not have a binding label (as if it were specified with
VALUEattribute is permitted to be an array, and is permitted to be of type
CHARACTERwith length non-constant and/or not equal to one. (It is still not permitted to have the
POINTERattributes, and is not permitted to be a coarray.)
The effect is that a copy is made of the actual argument, and the dummy argument is associated with the copy; any changes to the dummy argument do not affect the actual argument. For example,
PROGRAM value_example_2008 INTEGER :: a(3) = [ 1,2,3 ] CALL s('Hello?',a) PRINT '(7X,3I6)',a CONTAINS SUBROUTINE s(string,j) CHARACTER(*),VALUE :: string INTEGER,VALUE :: j(:) string(LEN(string):) = '!' j = j + 1 PRINT '(7X,A,3I6)',string,j END SUBROUTINE END PROGRAMwill produce the output
Hello! 2 3 4 1 2 3
A “separate module procedure” is a procedure whose interface is declared in the module
specification part, but whose definition may provided either in the module itself,
or in a submodule of that module.
The interface of a separate module procedure is declared by using the
in the prefix of the interface body.
INTERFACE MODULE RECURSIVE SUBROUTINE sub(x,y) REAL,INTENT(INOUT) :: x,y END SUBROUTINE END INTERFACEAn important aspect of the interface for a separate module procedure is that, unlike any other interface body, it accesses the module by host association without the need for an
IMPORTstatement. For example,
INTEGER,PARAMETER :: wp = SELECTED_REAL_KIND(15) INTERFACE MODULE REAL(wp) FUNCTION f(a,b) REAL(wp) a,b END FUNCTION END INTERFACEThe eventual definition of the separate module procedure, whether in the module itself or in a submodule, must have exactly the same characteristics, the same names for the dummy arguments, the same name for the result variable (if a function), the same binding-name (if it uses
BIND(C)), and be
RECURSIVEif and only if the interface is declared so. There are two ways to achieve this:
MODULEkeyword in the prefix, just like the definition. For example,
... CONTAINS MODULE REAL(wp) FUNCTION f(a,b) REAL(wp)a,b f = a**2 - b**3 END FUNCTION
MODULE PROCEDUREstatement in this context. For example,
... CONTAINS MODULE PROCEDURE sub ! Arguments A and B, their characteristics, and that this is a recursive subroutine, ! are all taken from the interface declaration. IF (a>b) THEN CALL sub(b,-ABS(a)) ELSE a = b**2 - a END IF END PROCEDURE
submodule-stmt declaration-part [ CONTAINS module-subprogram-part ] END [ SUBMODULE [ submodule-name ] ]The initial submodule-stmt has the form
SUBMODULE ( module-name [ : parent-submodule-name ] ) submodule-namewhere module-name is the name of a module with one or more separate module procedures, parent-submodule-name (if present) is the name of another submodule of that module, and submodule-name is the name of the submodule being defined. The submodules of a module thus form a tree structure, with successive submodules being able to extend others; however, the name of a submodule is unique within that module. This structure is to facilitate creation of internal infrastructure (types, constants, and procedures) that can be used by multiple submodules, without having to put all the infrastructure inside the module itself.
The submodule being defined accesses its parent module or submodule by host association;
for entities from the module, this includes access to
Any local entity it declares in the declaration-part will therefore block access to
an entity in the host that has the same name.
The entities (variables, types, procedures) declared by the submodule are local to that submodule, with the sole exception of separate module procedures that are declared in the ancestor module and defined in the submodule. No procedure is allowed to have a binding name, again, except in the case of a separate module procedure, where the binding name must be the same as in the interface.
MODULE mymod INTERFACE MODULE INTEGER FUNCTION next_number() RESULT(r) END FUNCTION MODULE SUBROUTINE reset() END SUBROUTINE END INTERFACE END MODULE SUBMODULE (mymod) variables INTEGER :: next = 1 END SUBMODULE SUBMODULE (mymod:variables) functions CONTAINS MODULE PROCEDURE next_number r = next next = next + 1 END PROCEDURE END SUBMODULE SUBMODULE (mymod:variables) subroutines CONTAINS MODULE SUBROUTINE reset() PRINT *,'Resetting' next = 1 END SUBROUTINE END SUBMODULE PROGRAM demo USE mymod PRINT *,'Hello',next_number() PRINT *,'Hello again',next_number() CALL reset PRINT *,'Hello last',next_number() END PROGRAM
Submodule information for use by other submodules is stored by the NAG Fortran Compiler in files
.sub, in a format similar to that of
The -nomod option, which suppresses creation of
also suppresses creation of
The Fortran 2008 standard, IS 1539-1:2010(E), is available from ISO as well as from many national standards bodies. A number of books describing the new standard are available; the recommended reference book is “Modern Fortran Explained (Incorporating Fortran 2018)” by Metcalf, Reid & Cohen, Oxford University Press, 2018 (ISBN 978-0-19-881188-6).