A categorization of standard (2018) and extended Fortran intrinsic procedures

This note attempts to group the intrinsic procedures of Fortran into categories of functions or subroutines with similar interfaces as an aid to comprehension beyond that which might be gained from the standard’s alphabetical list.

A brief status of intrinsic procedure support in f18 is also given at the end.

Few procedures are actually described here apart from their interfaces; see the Fortran 2018 standard (section 16) for the complete story.

Intrinsic modules are not covered here.

General rules

  1. The value of any intrinsic function’s KIND actual argument, if present, must be a scalar constant integer expression, of any kind, whose value resolves to some supported kind of the function’s result type. If optional and absent, the kind of the function’s result is either the default kind of that category or to the kind of an argument (e.g., as in AINT).

  2. Procedures are summarized with a non-Fortran syntax for brevity. Wherever a function has a short definition, it appears after an equal sign as if it were a statement function. Any functions referenced in these short summaries are intrinsic.

  3. Unless stated otherwise, an actual argument may have any supported kind of a particular intrinsic type. Sometimes a pattern variable can appear in a description (e.g., REAL(k)) when the kind of an actual argument’s type must match the kind of another argument, or determines the kind type parameter of the function result.

  4. When an intrinsic type name appears without a kind (e.g., REAL), it refers to the default kind of that type. Sometimes the word default will appear for clarity.

  5. The names of the dummy arguments actually matter because they can be used as keywords for actual arguments.

  6. All standard intrinsic functions are pure, even when not elemental.

  7. Assumed-rank arguments may not appear as actual arguments unless expressly permitted.

  8. When an argument is described with a default value, e.g. KIND=KIND(0), it is an optional argument. Optional arguments without defaults, e.g. DIM on many transformationals, are wrapped in [] brackets as in the Fortran standard. When an intrinsic has optional arguments with and without default values, the arguments with default values may appear within the brackets to preserve the order of arguments (e.g., COUNT).

Elemental intrinsic functions

Pure elemental semantics apply to these functions, to wit: when one or more of the actual arguments are arrays, the arguments must be conformable, and the result is also an array. Scalar arguments are expanded when the arguments are not all scalars.

Elemental intrinsic functions that may have unrestricted specific procedures

When an elemental intrinsic function is documented here as having an unrestricted specific name, that name may be passed as an actual argument, used as the target of a procedure pointer, appear in a generic interface, and be otherwise used as if it were an external procedure. An INTRINSIC statement or attribute may have to be applied to an unrestricted specific name to enable such usage.

When a name is being used as a specific procedure for any purpose other than that of a called function, the specific instance of the function that accepts and returns values of the default kinds of the intrinsic types is used. A Fortran INTERFACE could be written to define each of these unrestricted specific intrinsic function names.

Calls to dummy arguments and procedure pointers that correspond to these specific names must pass only scalar actual argument values.

No other intrinsic function name can be passed as an actual argument, used as a pointer target, appear in a generic interface, or be otherwise used except as the name of a called function. Some of these restricted specific intrinsic functions, e.g. FLOAT, provide a means for invoking a corresponding generic (REAL in the case of FLOAT) with forced argument and result kinds. Others, viz. CHAR, ICHAR, INT, REAL, and the lexical comparisons like LGE, have the same name as their generic functions, and it is not clear what purpose is accomplished by the standard by defining them as specific functions.

Trigonometric elemental intrinsic functions, generic and (mostly) specific

All of these functions can be used as unrestricted specific names.

ACOS(REAL(k) X) -> REAL(k)
ASIN(REAL(k) X) -> REAL(k)
ATAN(REAL(k) X) -> REAL(k)
ATAN(REAL(k) Y, REAL(k) X) -> REAL(k) = ATAN2(Y, X)
ATAN2(REAL(k) Y, REAL(k) X) -> REAL(k)
COS(REAL(k) X) -> REAL(k)
COSH(REAL(k) X) -> REAL(k)
SIN(REAL(k) X) -> REAL(k)
SINH(REAL(k) X) -> REAL(k)
TAN(REAL(k) X) -> REAL(k)
TANH(REAL(k) X) -> REAL(k)

These COMPLEX versions of some of those functions, and the inverse hyperbolic functions, cannot be used as specific names.

ACOS(COMPLEX(k) X) -> COMPLEX(k)
ASIN(COMPLEX(k) X) -> COMPLEX(k)
ATAN(COMPLEX(k) X) -> COMPLEX(k)
ACOSH(REAL(k) X) -> REAL(k)
ACOSH(COMPLEX(k) X) -> COMPLEX(k)
ASINH(REAL(k) X) -> REAL(k)
ASINH(COMPLEX(k) X) -> COMPLEX(k)
ATANH(REAL(k) X) -> REAL(k)
ATANH(COMPLEX(k) X) -> COMPLEX(k)
COS(COMPLEX(k) X) -> COMPLEX(k)
COSH(COMPLEX(k) X) -> COMPLEX(k)
SIN(COMPLEX(k) X) -> COMPLEX(k)
SINH(COMPLEX(k) X) -> COMPLEX(k)
TAN(COMPLEX(k) X) -> COMPLEX(k)
TANH(COMPLEX(k) X) -> COMPLEX(k)

Non-trigonometric elemental intrinsic functions, generic and specific

These functions can be used as unrestricted specific names.

ABS(REAL(k) A) -> REAL(k) = SIGN(A, 0.0)
AIMAG(COMPLEX(k) Z) -> REAL(k) = Z%IM
AINT(REAL(k) A, KIND=k) -> REAL(KIND)
ANINT(REAL(k) A, KIND=k) -> REAL(KIND)
CONJG(COMPLEX(k) Z) -> COMPLEX(k) = CMPLX(Z%RE, -Z%IM)
DIM(REAL(k) X, REAL(k) Y) -> REAL(k) = X-MIN(X,Y)
DPROD(default REAL X, default REAL Y) -> DOUBLE PRECISION = DBLE(X)*DBLE(Y)
EXP(REAL(k) X) -> REAL(k)
INDEX(CHARACTER(k) STRING, CHARACTER(k) SUBSTRING, LOGICAL(any) BACK=.FALSE., KIND=KIND(0)) -> INTEGER(KIND)
LEN(CHARACTER(k,n) STRING, KIND=KIND(0)) -> INTEGER(KIND) = n
LOG(REAL(k) X) -> REAL(k)
LOG10(REAL(k) X) -> REAL(k)
MOD(INTEGER(k) A, INTEGER(k) P) -> INTEGER(k) = A-P*INT(A/P)
NINT(REAL(k) A, KIND=KIND(0)) -> INTEGER(KIND)
SIGN(REAL(k) A, REAL(k) B) -> REAL(k)
SQRT(REAL(k) X) -> REAL(k) = X ** 0.5

These variants, however cannot be used as specific names without recourse to an alias from the following section:

ABS(INTEGER(k) A) -> INTEGER(k) = SIGN(A, 0)
ABS(COMPLEX(k) A) -> REAL(k) = HYPOT(A%RE, A%IM)
DIM(INTEGER(k) X, INTEGER(k) Y) -> INTEGER(k) = X-MIN(X,Y)
EXP(COMPLEX(k) X) -> COMPLEX(k)
LOG(COMPLEX(k) X) -> COMPLEX(k)
MOD(REAL(k) A, REAL(k) P) -> REAL(k) = A-P*INT(A/P)
SIGN(INTEGER(k) A, INTEGER(k) B) -> INTEGER(k)
SQRT(COMPLEX(k) X) -> COMPLEX(k)

Unrestricted specific aliases for some elemental intrinsic functions with distinct names

ALOG(REAL X) -> REAL = LOG(X)
ALOG10(REAL X) -> REAL = LOG10(X)
AMOD(REAL A, REAL P) -> REAL = MOD(A, P)
CABS(COMPLEX A) = ABS(A)
CCOS(COMPLEX X) = COS(X)
CEXP(COMPLEX A) -> COMPLEX = EXP(A)
CLOG(COMPLEX X) -> COMPLEX = LOG(X)
CSIN(COMPLEX X) -> COMPLEX = SIN(X)
CSQRT(COMPLEX X) -> COMPLEX = SQRT(X)
CTAN(COMPLEX X) -> COMPLEX = TAN(X)
DABS(DOUBLE PRECISION A) -> DOUBLE PRECISION = ABS(A)
DACOS(DOUBLE PRECISION X) -> DOUBLE PRECISION = ACOS(X)
DASIN(DOUBLE PRECISION X) -> DOUBLE PRECISION = ASIN(X)
DATAN(DOUBLE PRECISION X) -> DOUBLE PRECISION = ATAN(X)
DATAN2(DOUBLE PRECISION Y, DOUBLE PRECISION X) -> DOUBLE PRECISION = ATAN2(Y, X)
DCOS(DOUBLE PRECISION X) -> DOUBLE PRECISION = COS(X)
DCOSH(DOUBLE PRECISION X) -> DOUBLE PRECISION = COSH(X)
DDIM(DOUBLE PRECISION X, DOUBLE PRECISION Y) -> DOUBLE PRECISION = X-MIN(X,Y)
DEXP(DOUBLE PRECISION X) -> DOUBLE PRECISION = EXP(X)
DINT(DOUBLE PRECISION A) -> DOUBLE PRECISION = AINT(A)
DLOG(DOUBLE PRECISION X) -> DOUBLE PRECISION = LOG(X)
DLOG10(DOUBLE PRECISION X) -> DOUBLE PRECISION = LOG10(X)
DMOD(DOUBLE PRECISION A, DOUBLE PRECISION P) -> DOUBLE PRECISION = MOD(A, P)
DNINT(DOUBLE PRECISION A) -> DOUBLE PRECISION = ANINT(A)
DSIGN(DOUBLE PRECISION A, DOUBLE PRECISION B) -> DOUBLE PRECISION = SIGN(A, B)
DSIN(DOUBLE PRECISION X) -> DOUBLE PRECISION = SIN(X)
DSINH(DOUBLE PRECISION X) -> DOUBLE PRECISION = SINH(X)
DSQRT(DOUBLE PRECISION X) -> DOUBLE PRECISION = SQRT(X)
DTAN(DOUBLE PRECISION X) -> DOUBLE PRECISION = TAN(X)
DTANH(DOUBLE PRECISION X) -> DOUBLE PRECISION = TANH(X)
IABS(INTEGER A) -> INTEGER = ABS(A)
IDIM(INTEGER X, INTEGER Y) -> INTEGER = X-MIN(X,Y)
IDNINT(DOUBLE PRECISION A) -> INTEGER = NINT(A)
ISIGN(INTEGER A, INTEGER B) -> INTEGER = SIGN(A, B)

Generic elemental intrinsic functions without specific names

(No procedures after this point can be passed as actual arguments, used as pointer targets, or appear as specific procedures in generic interfaces.)

Elemental conversions

ACHAR(INTEGER(k) I, KIND=KIND('')) -> CHARACTER(KIND,LEN=1)
CEILING(REAL() A, KIND=KIND(0)) -> INTEGER(KIND)
CHAR(INTEGER(any) I, KIND=KIND('')) -> CHARACTER(KIND,LEN=1)
CMPLX(COMPLEX(k) X, KIND=KIND(0.0D0)) -> COMPLEX(KIND)
CMPLX(INTEGER or REAL or BOZ X, INTEGER or REAL or BOZ Y=0, KIND=KIND((0,0))) -> COMPLEX(KIND)
DBLE(INTEGER or REAL or COMPLEX or BOZ A) = REAL(A, KIND=KIND(0.0D0))
EXPONENT(REAL(any) X) -> default INTEGER
FLOOR(REAL(any) A, KIND=KIND(0)) -> INTEGER(KIND)
IACHAR(CHARACTER(KIND=k,LEN=1) C, KIND=KIND(0)) -> INTEGER(KIND)
ICHAR(CHARACTER(KIND=k,LEN=1) C, KIND=KIND(0)) -> INTEGER(KIND)
INT(INTEGER or REAL or COMPLEX or BOZ A, KIND=KIND(0)) -> INTEGER(KIND)
LOGICAL(LOGICAL(any) L, KIND=KIND(.TRUE.)) -> LOGICAL(KIND)
REAL(INTEGER or REAL or COMPLEX or BOZ A, KIND=KIND(0.0)) -> REAL(KIND)

Other generic elemental intrinsic functions without specific names

N.B. BESSEL_JN(N1, N2, X) and BESSEL_YN(N1, N2, X) are categorized below with the transformational intrinsic functions.

BESSEL_J0(REAL(k) X) -> REAL(k)
BESSEL_J1(REAL(k) X) -> REAL(k)
BESSEL_JN(INTEGER(n) N, REAL(k) X) -> REAL(k)
BESSEL_Y0(REAL(k) X) -> REAL(k)
BESSEL_Y1(REAL(k) X) -> REAL(k)
BESSEL_YN(INTEGER(n) N, REAL(k) X) -> REAL(k)
ERF(REAL(k) X) -> REAL(k)
ERFC(REAL(k) X) -> REAL(k)
ERFC_SCALED(REAL(k) X) -> REAL(k)
FRACTION(REAL(k) X) -> REAL(k)
GAMMA(REAL(k) X) -> REAL(k)
HYPOT(REAL(k) X, REAL(k) Y) -> REAL(k) = SQRT(X*X+Y*Y) without spurious overflow
IMAGE_STATUS(INTEGER(any) IMAGE [, scalar TEAM_TYPE TEAM ]) -> default INTEGER
IS_IOSTAT_END(INTEGER(any) I) -> default LOGICAL
IS_IOSTAT_EOR(INTEGER(any) I) -> default LOGICAL
LOG_GAMMA(REAL(k) X) -> REAL(k)
MAX(INTEGER(k) ...) -> INTEGER(k)
MAX(REAL(k) ...) -> REAL(k)
MAX(CHARACTER(KIND=k) ...) -> CHARACTER(KIND=k,LEN=MAX(LEN(...)))
MERGE(any type TSOURCE, same type FSOURCE, LOGICAL(any) MASK) -> type of FSOURCE
MIN(INTEGER(k) ...) -> INTEGER(k)
MIN(REAL(k) ...) -> REAL(k)
MIN(CHARACTER(KIND=k) ...) -> CHARACTER(KIND=k,LEN=MAX(LEN(...)))
MODULO(INTEGER(k) A, INTEGER(k) P) -> INTEGER(k); P*result >= 0
MODULO(REAL(k) A, REAL(k) P) -> REAL(k) = A - P*FLOOR(A/P)
NEAREST(REAL(k) X, REAL(any) S) -> REAL(k)
OUT_OF_RANGE(INTEGER(any) X, scalar INTEGER or REAL(k) MOLD) -> default LOGICAL
OUT_OF_RANGE(REAL(any) X, scalar REAL(k) MOLD) -> default LOGICAL
OUT_OF_RANGE(REAL(any) X, scalar INTEGER(any) MOLD, scalar LOGICAL(any) ROUND=.FALSE.) -> default LOGICAL
RRSPACING(REAL(k) X) -> REAL(k)
SCALE(REAL(k) X, INTEGER(any) I) -> REAL(k)
SET_EXPONENT(REAL(k) X, INTEGER(any) I) -> REAL(k)
SPACING(REAL(k) X) -> REAL(k)

Restricted specific aliases for elemental conversions &/or extrema with default intrinsic types

AMAX0(INTEGER ...) = REAL(MAX(...))
AMAX1(REAL ...) = MAX(...)
AMIN0(INTEGER...) = REAL(MIN(...))
AMIN1(REAL ...) = MIN(...)
DMAX1(DOUBLE PRECISION ...) = MAX(...)
DMIN1(DOUBLE PRECISION ...) = MIN(...)
FLOAT(INTEGER I) = REAL(I)
IDINT(DOUBLE PRECISION A) = INT(A)
IFIX(REAL A) = INT(A)
MAX0(INTEGER ...) = MAX(...)
MAX1(REAL ...) = INT(MAX(...))
MIN0(INTEGER ...) = MIN(...)
MIN1(REAL ...) = INT(MIN(...))
SNGL(DOUBLE PRECISION A) = REAL(A)

Generic elemental bit manipulation intrinsic functions

Many of these accept a typeless “BOZ” literal as an actual argument. It is interpreted as having the kind of intrinsic INTEGER type as another argument, as if the typeless were implicitly wrapped in a call to INT(). When multiple arguments can be either INTEGER values or typeless constants, it is forbidden for all of them to be typeless constants if the result of the function is INTEGER (i.e., only BGE, BGT, BLE, and BLT can have multiple typeless arguments).

BGE(INTEGER(n1) or BOZ I, INTEGER(n2) or BOZ J) -> default LOGICAL
BGT(INTEGER(n1) or BOZ I, INTEGER(n2) or BOZ J) -> default LOGICAL
BLE(INTEGER(n1) or BOZ I, INTEGER(n2) or BOZ J) -> default LOGICAL
BLT(INTEGER(n1) or BOZ I, INTEGER(n2) or BOZ J) -> default LOGICAL
BTEST(INTEGER(n1) I, INTEGER(n2) POS) -> default LOGICAL
DSHIFTL(INTEGER(k) I, INTEGER(k) or BOZ J, INTEGER(any) SHIFT) -> INTEGER(k)
DSHIFTL(BOZ I, INTEGER(k), INTEGER(any) SHIFT) -> INTEGER(k)
DSHIFTR(INTEGER(k) I, INTEGER(k) or BOZ J, INTEGER(any) SHIFT) -> INTEGER(k)
DSHIFTR(BOZ I, INTEGER(k), INTEGER(any) SHIFT) -> INTEGER(k)
IAND(INTEGER(k) I, INTEGER(k) or BOZ J) -> INTEGER(k)
IAND(BOZ I, INTEGER(k) J) -> INTEGER(k)
IBCLR(INTEGER(k) I, INTEGER(any) POS) -> INTEGER(k)
IBITS(INTEGER(k) I, INTEGER(n1) POS, INTEGER(n2) LEN) -> INTEGER(k)
IBSET(INTEGER(k) I, INTEGER(any) POS) -> INTEGER(k)
IEOR(INTEGER(k) I, INTEGER(k) or BOZ J) -> INTEGER(k)
IEOR(BOZ I, INTEGER(k) J) -> INTEGER(k)
IOR(INTEGER(k) I, INTEGER(k) or BOZ J) -> INTEGER(k)
IOR(BOZ I, INTEGER(k) J) -> INTEGER(k)
ISHFT(INTEGER(k) I, INTEGER(any) SHIFT) -> INTEGER(k)
ISHFTC(INTEGER(k) I, INTEGER(n1) SHIFT, INTEGER(n2) SIZE=BIT_SIZE(I)) -> INTEGER(k)
LEADZ(INTEGER(any) I) -> default INTEGER
MASKL(INTEGER(any) I, KIND=KIND(0)) -> INTEGER(KIND)
MASKR(INTEGER(any) I, KIND=KIND(0)) -> INTEGER(KIND)
MERGE_BITS(INTEGER(k) I, INTEGER(k) or BOZ J, INTEGER(k) or BOZ MASK) = IOR(IAND(I,MASK),IAND(J,NOT(MASK)))
MERGE_BITS(BOZ I, INTEGER(k) J, INTEGER(k) or BOZ MASK) = IOR(IAND(I,MASK),IAND(J,NOT(MASK)))
NOT(INTEGER(k) I) -> INTEGER(k)
POPCNT(INTEGER(any) I) -> default INTEGER
POPPAR(INTEGER(any) I) -> default INTEGER = IAND(POPCNT(I), Z'1')
SHIFTA(INTEGER(k) I, INTEGER(any) SHIFT) -> INTEGER(k)
SHIFTL(INTEGER(k) I, INTEGER(any) SHIFT) -> INTEGER(k)
SHIFTR(INTEGER(k) I, INTEGER(any) SHIFT) -> INTEGER(k)
TRAILZ(INTEGER(any) I) -> default INTEGER

Character elemental intrinsic functions

See also INDEX and LEN above among the elemental intrinsic functions with unrestricted specific names.

ADJUSTL(CHARACTER(k,LEN=n) STRING) -> CHARACTER(k,LEN=n)
ADJUSTR(CHARACTER(k,LEN=n) STRING) -> CHARACTER(k,LEN=n)
LEN_TRIM(CHARACTER(k,n) STRING, KIND=KIND(0)) -> INTEGER(KIND) = n
LGE(CHARACTER(k,n1) STRING_A, CHARACTER(k,n2) STRING_B) -> default LOGICAL
LGT(CHARACTER(k,n1) STRING_A, CHARACTER(k,n2) STRING_B) -> default LOGICAL
LLE(CHARACTER(k,n1) STRING_A, CHARACTER(k,n2) STRING_B) -> default LOGICAL
LLT(CHARACTER(k,n1) STRING_A, CHARACTER(k,n2) STRING_B) -> default LOGICAL
SCAN(CHARACTER(k,n) STRING, CHARACTER(k,m) SET, LOGICAL(any) BACK=.FALSE., KIND=KIND(0)) -> INTEGER(KIND)
VERIFY(CHARACTER(k,n) STRING, CHARACTER(k,m) SET, LOGICAL(any) BACK=.FALSE., KIND=KIND(0)) -> INTEGER(KIND)

SCAN returns the index of the first (or last, if BACK=.TRUE.) character in STRING that is present in SET, or zero if none is.

VERIFY is essentially the opposite: it returns the index of the first (or last) character in STRING that is not present in SET, or zero if all are.

Transformational intrinsic functions

This category comprises a large collection of intrinsic functions that are collected together because they somehow transform their arguments in a way that prevents them from being elemental. All of them are pure, however.

Some general rules apply to the transformational intrinsic functions:

  1. DIM arguments are optional; if present, the actual argument must be a scalar integer of any kind.

  2. When an optional DIM argument is absent, or an ARRAY or MASK argument is a vector, the result of the function is scalar; otherwise, the result is an array of the same shape as the ARRAY or MASK argument with the dimension DIM removed from the shape.

  3. When a function takes an optional MASK argument, it must be conformable with its ARRAY argument if it is present, and the mask can be any kind of LOGICAL. It can be scalar.

  4. The type numeric here can be any kind of INTEGER, REAL, or COMPLEX.

  5. The type relational here can be any kind of INTEGER, REAL, or CHARACTER.

  6. The type any here denotes any intrinsic or derived type.

  7. The notation (..) denotes an array of any rank (but not an assumed-rank array).

Logical reduction transformational intrinsic functions

ALL(LOGICAL(k) MASK(..) [, DIM ]) -> LOGICAL(k)
ANY(LOGICAL(k) MASK(..) [, DIM ]) -> LOGICAL(k)
COUNT(LOGICAL(any) MASK(..) [, DIM, KIND=KIND(0) ]) -> INTEGER(KIND)
PARITY(LOGICAL(k) MASK(..) [, DIM ]) -> LOGICAL(k)

Numeric reduction transformational intrinsic functions

IALL(INTEGER(k) ARRAY(..) [, DIM, MASK ]) -> INTEGER(k)
IANY(INTEGER(k) ARRAY(..) [, DIM, MASK ]) -> INTEGER(k)
IPARITY(INTEGER(k) ARRAY(..) [, DIM, MASK ]) -> INTEGER(k)
NORM2(REAL(k) X(..) [, DIM ]) -> REAL(k)
PRODUCT(numeric ARRAY(..) [, DIM, MASK ]) -> numeric
SUM(numeric ARRAY(..) [, DIM, MASK ]) -> numeric

NORM2 generalizes HYPOT by computing SQRT(SUM(X*X)) while avoiding spurious overflows.

Extrema reduction transformational intrinsic functions

MAXVAL(relational(k) ARRAY(..) [, DIM, MASK ]) -> relational(k)
MINVAL(relational(k) ARRAY(..) [, DIM, MASK ]) -> relational(k)

Locational transformational intrinsic functions

When the optional DIM argument is absent, the result is an INTEGER(KIND) vector whose length is the rank of ARRAY. When the optional DIM argument is present, the result is an INTEGER(KIND) array of rank RANK(ARRAY)-1 and shape equal to that of ARRAY with the dimension DIM removed.

The optional BACK argument is a scalar LOGICAL value of any kind. When present and .TRUE., it causes the function to return the index of the last occurence of the target or extreme value.

For FINDLOC, ARRAY may have any of the five intrinsic types, and VALUE must a scalar value of a type for which ARRAY==VALUE or ARRAY .EQV. VALUE is an acceptable expression.

FINDLOC(intrinsic ARRAY(..), scalar VALUE [, DIM, MASK, KIND=KIND(0), BACK=.FALSE. ])
MAXLOC(relational ARRAY(..) [, DIM, MASK, KIND=KIND(0), BACK=.FALSE. ])
MINLOC(relational ARRAY(..) [, DIM, MASK, KIND=KIND(0), BACK=.FALSE. ])

Data rearrangement transformational intrinsic functions

The optional DIM argument to these functions must be a scalar integer of any kind, and it takes a default value of 1 when absent.

CSHIFT(any ARRAY(..), INTEGER(any) SHIFT(..) [, DIM ]) -> same type/kind/shape as ARRAY

Either SHIFT is scalar or RANK(SHIFT) == RANK(ARRAY) - 1 and SHAPE(SHIFT) is that of SHAPE(ARRAY) with element DIM removed.

EOSHIFT(any ARRAY(..), INTEGER(any) SHIFT(..) [, BOUNDARY, DIM ]) -> same type/kind/shape as ARRAY
  • SHIFT is scalar or RANK(SHIFT) == RANK(ARRAY) - 1 and SHAPE(SHIFT) is that of SHAPE(ARRAY) with element DIM removed.

  • If BOUNDARY is present, it must have the same type and parameters as ARRAY.

  • If BOUNDARY is absent, ARRAY must be of an intrinsic type, and the default BOUNDARY is the obvious 0, ' ', or .FALSE. value of KIND(ARRAY).

  • If BOUNDARY is present, either it is scalar, or RANK(BOUNDARY) == RANK(ARRAY) - 1 and SHAPE(BOUNDARY) is that of SHAPE(ARRAY) with element DIM removed.

PACK(any ARRAY(..), LOGICAL(any) MASK(..)) -> vector of same type and kind as ARRAY
  • MASK is conformable with ARRAY and may be scalar.

  • The length of the result vector is COUNT(MASK) if MASK is an array, else SIZE(ARRAY) if MASK is .TRUE., else zero.

PACK(any ARRAY(..), LOGICAL(any) MASK(..), any VECTOR(n)) -> vector of same type, kind, and size as VECTOR
  • MASK is conformable with ARRAY and may be scalar.

  • VECTOR has the same type and kind as ARRAY.

  • VECTOR must not be smaller than result of PACK with no VECTOR argument.

  • The leading elements of VECTOR are replaced with elements from ARRAY as if PACK had been invoked without VECTOR.

RESHAPE(any SOURCE(..), INTEGER(k) SHAPE(n) [, PAD(..), INTEGER(k2) ORDER(n) ]) -> SOURCE array with shape SHAPE
  • If ORDER is present, it is a vector of the same size as SHAPE, and contains a permutation.

  • The element(s) of PAD are used to fill out the result once SOURCE has been consumed.

SPREAD(any SOURCE, DIM, scalar INTEGER(any) NCOPIES) -> same type as SOURCE, rank=RANK(SOURCE)+1
TRANSFER(any SOURCE, any MOLD) -> scalar if MOLD is scalar, else vector; same type and kind as MOLD
TRANSFER(any SOURCE, any MOLD, scalar INTEGER(any) SIZE) -> vector(SIZE) of type and kind of MOLD
TRANSPOSE(any MATRIX(n,m)) -> matrix(m,n) of same type and kind as MATRIX

The shape of the result of SPREAD is the same as that of SOURCE, with NCOPIES inserted at position DIM.

UNPACK(any VECTOR(n), LOGICAL(any) MASK(..), FIELD) -> type and kind of VECTOR, shape of MASK

FIELD has same type and kind as VECTOR and is conformable with MASK.

Other transformational intrinsic functions

BESSEL_JN(INTEGER(n1) N1, INTEGER(n2) N2, REAL(k) X) -> REAL(k) vector (MAX(N2-N1+1,0))
BESSEL_YN(INTEGER(n1) N1, INTEGER(n2) N2, REAL(k) X) -> REAL(k) vector (MAX(N2-N1+1,0))
COMMAND_ARGUMENT_COUNT() -> scalar default INTEGER
DOT_PRODUCT(LOGICAL(k) VECTOR_A(n), LOGICAL(k) VECTOR_B(n)) -> LOGICAL(k) = ANY(VECTOR_A .AND. VECTOR_B)
DOT_PRODUCT(COMPLEX(any) VECTOR_A(n), numeric VECTOR_B(n)) = SUM(CONJG(VECTOR_A) * VECTOR_B)
DOT_PRODUCT(INTEGER(any) or REAL(any) VECTOR_A(n), numeric VECTOR_B(n)) = SUM(VECTOR_A * VECTOR_B)
MATMUL(numeric ARRAY_A(j), numeric ARRAY_B(j,k)) -> numeric vector(k)
MATMUL(numeric ARRAY_A(j,k), numeric ARRAY_B(k)) -> numeric vector(j)
MATMUL(numeric ARRAY_A(j,k), numeric ARRAY_B(k,m)) -> numeric matrix(j,m)
MATMUL(LOGICAL(n1) ARRAY_A(j), LOGICAL(n2) ARRAY_B(j,k)) -> LOGICAL vector(k)
MATMUL(LOGICAL(n1) ARRAY_A(j,k), LOGICAL(n2) ARRAY_B(k)) -> LOGICAL vector(j)
MATMUL(LOGICAL(n1) ARRAY_A(j,k), LOGICAL(n2) ARRAY_B(k,m)) -> LOGICAL matrix(j,m)
NULL([POINTER/ALLOCATABLE MOLD]) -> POINTER
REDUCE(any ARRAY(..), function OPERATION [, DIM, LOGICAL(any) MASK(..), IDENTITY, LOGICAL ORDERED=.FALSE. ])
REPEAT(CHARACTER(k,n) STRING, INTEGER(any) NCOPIES) -> CHARACTER(k,n*NCOPIES)
SELECTED_CHAR_KIND('DEFAULT' or 'ASCII' or 'ISO_10646' or ...) -> scalar default INTEGER
SELECTED_INT_KIND(scalar INTEGER(any) R) -> scalar default INTEGER
SELECTED_REAL_KIND([scalar INTEGER(any) P, scalar INTEGER(any) R, scalar INTEGER(any) RADIX]) -> scalar default INTEGER
SHAPE(SOURCE, KIND=KIND(0)) -> INTEGER(KIND)(RANK(SOURCE))
TRIM(CHARACTER(k,n) STRING) -> CHARACTER(k)

The type and kind of the result of a numeric MATMUL is the same as would result from a multiplication of an element of ARRAY_A and an element of ARRAY_B.

The kind of the LOGICAL result of a LOGICAL MATMUL is the same as would result from an intrinsic .AND. operation between an element of ARRAY_A and an element of ARRAY_B.

Note that DOT_PRODUCT with a COMPLEX first argument operates on its complex conjugate, but that MATMUL with a COMPLEX argument does not.

The MOLD argument to NULL may be omitted only in a context where the type of the pointer is known, such as an initializer or pointer assignment statement.

At least one argument must be present in a call to SELECTED_REAL_KIND.

An assumed-rank array may be passed to SHAPE, and if it is associated with an assumed-size array, the last element of the result will be -1.

Coarray transformational intrinsic functions

FAILED_IMAGES([scalar TEAM_TYPE TEAM, KIND=KIND(0)]) -> INTEGER(KIND) vector
GET_TEAM([scalar INTEGER(?) LEVEL]) -> scalar TEAM_TYPE
IMAGE_INDEX(COARRAY, INTEGER(any) SUB(n) [, scalar TEAM_TYPE TEAM ]) -> scalar default INTEGER
IMAGE_INDEX(COARRAY, INTEGER(any) SUB(n), scalar INTEGER(any) TEAM_NUMBER) -> scalar default INTEGER
NUM_IMAGES([scalar TEAM_TYPE TEAM]) -> scalar default INTEGER
NUM_IMAGES(scalar INTEGER(any) TEAM_NUMBER) -> scalar default INTEGER
STOPPED_IMAGES([scalar TEAM_TYPE TEAM, KIND=KIND(0)]) -> INTEGER(KIND) vector
TEAM_NUMBER([scalar TEAM_TYPE TEAM]) -> scalar default INTEGER
THIS_IMAGE([COARRAY, DIM, scalar TEAM_TYPE TEAM]) -> default INTEGER

The result of THIS_IMAGE is a scalar if DIM is present or if COARRAY is absent, and a vector whose length is the corank of COARRAY otherwise.

Inquiry intrinsic functions

These are neither elemental nor transformational; all are pure.

Type inquiry intrinsic functions

All of these functions return constants. The value of the argument is not used, and may well be undefined.

BIT_SIZE(INTEGER(k) I(..)) -> INTEGER(k)
DIGITS(INTEGER or REAL X(..)) -> scalar default INTEGER
EPSILON(REAL(k) X(..)) -> scalar REAL(k)
HUGE(INTEGER(k) X(..)) -> scalar INTEGER(k)
HUGE(REAL(k) X(..)) -> scalar of REAL(k)
KIND(intrinsic X(..)) -> scalar default INTEGER
MAXEXPONENT(REAL(k) X(..)) -> scalar default INTEGER
MINEXPONENT(REAL(k) X(..)) -> scalar default INTEGER
NEW_LINE(CHARACTER(k,n) A(..)) -> scalar CHARACTER(k,1) = CHAR(10)
PRECISION(REAL(k) or COMPLEX(k) X(..)) -> scalar default INTEGER
RADIX(INTEGER(k) or REAL(k) X(..)) -> scalar default INTEGER, always 2
RANGE(INTEGER(k) or REAL(k) or COMPLEX(k) X(..)) -> scalar default INTEGER
TINY(REAL(k) X(..)) -> scalar REAL(k)

Bound and size inquiry intrinsic functions

The results are scalar when DIM is present, and a vector of length=(co)rank((CO)ARRAY) when DIM is absent.

LBOUND(any ARRAY(..) [, DIM, KIND=KIND(0) ]) -> INTEGER(KIND)
LCOBOUND(any COARRAY [, DIM, KIND=KIND(0) ]) -> INTEGER(KIND)
SIZE(any ARRAY(..) [, DIM, KIND=KIND(0) ]) -> INTEGER(KIND)
UBOUND(any ARRAY(..) [, DIM, KIND=KIND(0) ]) -> INTEGER(KIND)
UCOBOUND(any COARRAY [, DIM, KIND=KIND(0) ]) -> INTEGER(KIND)

Assumed-rank arrays may be used with LBOUND, SIZE, and UBOUND.

Object characteristic inquiry intrinsic functions

ALLOCATED(any type ALLOCATABLE ARRAY) -> scalar default LOGICAL
ALLOCATED(any type ALLOCATABLE SCALAR) -> scalar default LOGICAL
ASSOCIATED(any type POINTER POINTER [, same type TARGET]) -> scalar default LOGICAL
COSHAPE(COARRAY, KIND=KIND(0)) -> INTEGER(KIND) vector of length corank(COARRAY)
EXTENDS_TYPE_OF(A, MOLD) -> default LOGICAL
IS_CONTIGUOUS(any data ARRAY(..)) -> scalar default LOGICAL
PRESENT(OPTIONAL A) -> scalar default LOGICAL
RANK(any data A) -> scalar default INTEGER = 0 if A is scalar, SIZE(SHAPE(A)) if A is an array, rank if assumed-rank
SAME_TYPE_AS(A, B) -> scalar default LOGICAL
STORAGE_SIZE(any data A, KIND=KIND(0)) -> INTEGER(KIND)

The arguments to EXTENDS_TYPE_OF must be of extensible derived types or be unlimited polymorphic.

An assumed-rank array may be used with IS_CONTIGUOUS and RANK.

Intrinsic subroutines

(TODO: complete these descriptions)

One elemental intrinsic subroutine

INTERFACE
  SUBROUTINE MVBITS(FROM, FROMPOS, LEN, TO, TOPOS)
    INTEGER(k1) :: FROM, TO
    INTENT(IN) :: FROM
    INTENT(INOUT) :: TO
    INTEGER(k2), INTENT(IN) :: FROMPOS
    INTEGER(k3), INTENT(IN) :: LEN
    INTEGER(k4), INTENT(IN) :: TOPOS
  END SUBROUTINE
END INTERFACE

Non-elemental intrinsic subroutines

CALL CPU_TIME(REAL INTENT(OUT) TIME)

The kind of TIME is not specified in the standard.

CALL DATE_AND_TIME([DATE, TIME, ZONE, VALUES])
  • All arguments are OPTIONAL and INTENT(OUT).

  • DATE, TIME, and ZONE are scalar default CHARACTER.

  • VALUES is a vector of at least 8 elements of INTEGER(KIND >= 2).

CALL EVENT_QUERY(EVENT, COUNT [, STAT])
CALL EXECUTE_COMMAND_LINE(COMMAND [, WAIT, EXITSTAT, CMDSTAT, CMDMSG ])
CALL GET_COMMAND([COMMAND, LENGTH, STATUS, ERRMSG ])
CALL GET_COMMAND_ARGUMENT(NUMBER [, VALUE, LENGTH, STATUS, ERRMSG ])
CALL GET_ENVIRONMENT_VARIABLE(NAME [, VALUE, LENGTH, STATUS, TRIM_NAME, ERRMSG ])
CALL MOVE_ALLOC(ALLOCATABLE INTENT(INOUT) FROM, ALLOCATABLE INTENT(OUT) TO [, STAT, ERRMSG ])
CALL RANDOM_INIT(LOGICAL(k1) INTENT(IN) REPEATABLE, LOGICAL(k2) INTENT(IN) IMAGE_DISTINCT)
CALL RANDOM_NUMBER(REAL(k) INTENT(OUT) HARVEST(..))
CALL RANDOM_SEED([SIZE, PUT, GET])
CALL SYSTEM_CLOCK([COUNT, COUNT_RATE, COUNT_MAX])

Atomic intrinsic subroutines

CALL ATOMIC_ADD(ATOM, VALUE [, STAT=])
CALL ATOMIC_AND(ATOM, VALUE [, STAT=])
CALL ATOMIC_CAS(ATOM, OLD, COMPARE, NEW [, STAT=])
CALL ATOMIC_DEFINE(ATOM, VALUE [, STAT=])
CALL ATOMIC_FETCH_ADD(ATOM, VALUE, OLD [, STAT=])
CALL ATOMIC_FETCH_AND(ATOM, VALUE, OLD [, STAT=])
CALL ATOMIC_FETCH_OR(ATOM, VALUE, OLD [, STAT=])
CALL ATOMIC_FETCH_XOR(ATOM, VALUE, OLD [, STAT=])
CALL ATOMIC_OR(ATOM, VALUE [, STAT=])
CALL ATOMIC_REF(VALUE, ATOM [, STAT=])
CALL ATOMIC_XOR(ATOM, VALUE [, STAT=])

Collective intrinsic subroutines

CALL CO_BROADCAST
CALL CO_MAX
CALL CO_MIN
CALL CO_REDUCE
CALL CO_SUM

Inquiry Functions

ACCESS (GNU extension) is not supported on Windows. Otherwise:

CHARACTER(LEN=*) :: path = 'path/to/file'
IF (ACCESS(path, 'rwx')) &
  ...

Non-standard intrinsics

PGI

AND, OR, XOR
LSHIFT, RSHIFT, SHIFT
ZEXT, IZEXT
COSD, SIND, TAND, ACOSD, ASIND, ATAND, ATAN2D
COMPL
DCMPLX
EQV, NEQV
INT8
JINT, JNINT, KNINT
LOC

Intel

DCMPLX(X,Y), QCMPLX(X,Y)
DREAL(DOUBLE COMPLEX A) -> DOUBLE PRECISION
DFLOAT, DREAL
QEXT, QFLOAT, QREAL
DNUM, INUM, JNUM, KNUM, QNUM, RNUM - scan value from string
ZEXT
RAN, RANF
ILEN(I) = BIT_SIZE(I)
SIZEOF
MCLOCK, SECNDS
COTAN(X) = 1.0/TAN(X)
COSD, SIND, TAND, ACOSD, ASIND, ATAND, ATAN2D, COTAND - degrees
AND, OR, XOR
LSHIFT, RSHIFT
IBCHNG, ISHA, ISHC, ISHL, IXOR
IARG, IARGC, NARGS, NUMARG
BADDRESS, IADDR
CACHESIZE, EOF, FP_CLASS, INT_PTR_KIND, ISNAN, LOC
MALLOC, FREE

Library subroutine

CALL FDATE(TIME)
CALL GETLOG(USRNAME)
CALL GETENV(NAME [, VALUE, LENGTH, STATUS, TRIM_NAME, ERRMSG ])

Intrinsic Procedure Name Resolution

When the name of a procedure in a program is the same as the one of an intrinsic procedure, and nothing other than its usage allows to decide whether the procedure is the intrinsic or not (i.e, it does not appear in an INTRINSIC or EXTERNAL attribute statement, is not an use/host associated procedure…), Fortran 2018 standard section 19.5.1.4 point 6 rules that the procedure is established to be intrinsic if it is invoked as an intrinsic procedure.

In case the invocation would be an error if the procedure were the intrinsic (e.g. wrong argument number or type), the broad wording of the standard leaves two choices to the compiler: emit an error about the intrinsic invocation, or consider this is an external procedure and emit no error.

f18 will always consider this case to be the intrinsic and emit errors, unless the procedure is used as a function (resp. subroutine) and the intrinsic is a subroutine (resp. function). The table below gives some examples of decisions made by Fortran compilers in such case.

What is ACOS ?

Bad intrinsic call

External with warning

External no warning

Other error

print*, ACOS()

gfortran, nag, xlf, f18

ifort

nvfortran

print*, ACOS(I)

gfortran, nag, xlf, f18

ifort

nvfortran

print*, ACOS(X=I)

gfortran, nag, xlf, f18

ifort

nvfortran (keyword on implicit extrenal )

print*, ACOS(X, X)

gfortran, nag, xlf, f18

ifort

nvfortran

CALL ACOS(X)

gfortran, nag, xlf, nvfortran, ifort, f18

The rationale for f18 behavior is that when referring to a procedure with an argument number or type that does not match the intrinsic specification, it seems safer to block the rather likely case where the user is using the intrinsic the wrong way. In case the user wanted to refer to an external function, he can add an explicit EXTERNAL statement with no other consequences on the program. However, it seems rather unlikely that a user would confuse an intrinsic subroutine for a function and vice versa. Given no compiler is issuing an error here, changing the behavior might affect existing programs that omit the EXTERNAL attribute in such case.

Also note that in general, the standard gives the compiler the right to consider any procedure that is not explicitly external as a non standard intrinsic (section 4.2 point 4). So it is highly advised for the programmer to use EXTERNAL statements to prevent any ambiguity.

Intrinsic Procedure Support in f18

This section gives an overview of the support inside f18 libraries for the intrinsic procedures listed above. It may be outdated, refer to f18 code base for the actual support status.

Semantic Analysis

F18 semantic expression analysis phase detects intrinsic procedure references, validates the argument types and deduces the return types. This phase currently supports all the intrinsic procedures listed above but the ones in the table below.

Intrinsic Category

Intrinsic Procedures Lacking Support

Coarray intrinsic functions

COSHAPE

Object characteristic inquiry functions

ALLOCATED, ASSOCIATED, EXTENDS_TYPE_OF, IS_CONTIGUOUS, PRESENT, RANK, SAME_TYPE, STORAGE_SIZE

Type inquiry intrinsic functions

BIT_SIZE, DIGITS, EPSILON, HUGE, KIND, MAXEXPONENT, MINEXPONENT, NEW_LINE, PRECISION, RADIX, RANGE, TINY

Non-standard intrinsic functions

AND, OR, XOR, SHIFT, ZEXT, IZEXT, COSD, SIND, TAND, ACOSD, ASIND, ATAND, ATAN2D, COMPL, EQV, NEQV, INT8, JINT, JNINT, KNINT, QCMPLX, DREAL, DFLOAT, QEXT, QFLOAT, QREAL, DNUM, NUM, JNUM, KNUM, QNUM, RNUM, RAN, RANF, ILEN, SIZEOF, MCLOCK, SECNDS, COTAN, IBCHNG, ISHA, ISHC, ISHL, IXOR, IARG, IARGC, NARGS, GETPID, NUMARG, BADDRESS, IADDR, CACHESIZE, EOF, FP_CLASS, INT_PTR_KIND, ISNAN, MALLOC, FREE, GETUID, GETGID

Intrinsic subroutines

MVBITS (elemental), CPU_TIME, DATE_AND_TIME, EVENT_QUERY, EXECUTE_COMMAND_LINE, GET_COMMAND, GET_COMMAND_ARGUMENT, GET_ENVIRONMENT_VARIABLE, MOVE_ALLOC, RANDOM_INIT, RANDOM_NUMBER, RANDOM_SEED, SIGNAL, SLEEP, SYSTEM, SYSTEM_CLOCK

Atomic intrinsic subroutines

ATOMIC_ADD

Collective intrinsic subroutines

CO_REDUCE

Library subroutines

FDATE, GETLOG, GETENV

Intrinsic Function Folding

Fortran Constant Expressions can contain references to a certain number of intrinsic functions (see Fortran 2018 standard section 10.1.12 for more details). Constant Expressions may be used to define kind arguments. Therefore, the semantic expression analysis phase must be able to fold references to intrinsic functions listed in section 10.1.12.

F18 intrinsic function folding is either performed by implementations directly operating on f18 scalar types or by using host runtime functions and host hardware types. F18 supports folding elemental intrinsic functions over arrays when an implementation is provided for the scalars (regardless of whether it is using host hardware types or not). The status of intrinsic function folding support is given in the sub-sections below.

Intrinsic Functions with Host Independent Folding Support

Implementations using f18 scalar types enables folding intrinsic functions on any host and with any possible type kind supported by f18. The intrinsic functions listed below are folded using host independent implementations.

Return Type

Intrinsic Functions with Host Independent Folding Support

INTEGER

ABS(INTEGER(k)), DIM(INTEGER(k), INTEGER(k)), DSHIFTL, DSHIFTR, IAND, IBCLR, IBSET, IEOR, INT, IOR, ISHFT, KIND, LEN, LEADZ, MASKL, MASKR, MERGE_BITS, POPCNT, POPPAR, SHIFTA, SHIFTL, SHIFTR, TRAILZ

REAL

ABS(REAL(k)), ABS(COMPLEX(k)), AIMAG, AINT, DPROD, REAL

COMPLEX

CMPLX, CONJG

LOGICAL

BGE, BGT, BLE, BLT

Intrinsic Functions with Host Dependent Folding Support

Implementations using the host runtime may not be available for all supported f18 types depending on the host hardware types and the libraries available on the host. The actual support on a host depends on what the host hardware types are. The list below gives the functions that are folded using host runtime and the related C/C++ types. F18 automatically detects if these types match an f18 scalar type. If so, folding of the intrinsic functions will be possible for the related f18 scalar type, otherwise an error message will be produced by f18 when attempting to fold related intrinsic functions.

C/C++ Host Type

Intrinsic Functions with Host Standard C++ Library Based Folding Support

float, double and long double

ACOS, ACOSH, ASINH, ATAN, ATAN2, ATANH, COS, COSH, ERF, ERFC, EXP, GAMMA, HYPOT, LOG, LOG10, LOG_GAMMA, MOD, SIN, SQRT, SINH, SQRT, TAN, TANH

std::complex for float, double and long double

ACOS, ACOSH, ASIN, ASINH, ATAN, ATANH, COS, COSH, EXP, LOG, SIN, SINH, SQRT, TAN, TANH

On top of the default usage of C++ standard library functions for folding described in the table above, it is possible to compile f18 evaluate library with libpgmath so that it can be used for folding. To do so, one must have a compiled version of the libpgmath library available on the host and add -DLIBPGMATH_DIR=<path to the compiled shared libpgmath library> to the f18 cmake command.

Libpgmath comes with real and complex functions that replace C++ standard library float and double functions to fold all the intrinsic functions listed in the table above. It has no long double versions. If the host long double matches an f18 scalar type, C++ standard library functions will still be used for folding expressions with this scalar type. Libpgmath adds the possibility to fold the following functions for f18 real scalar types related to host float and double types.

C/C++ Host Type

Additional Intrinsic Function Folding Support with Libpgmath (Optional)

float and double

BESSEL_J0, BESSEL_J1, BESSEL_JN (elemental only), BESSEL_Y0, BESSEL_Y1, BESSEL_Yn (elemental only), ERFC_SCALED

Libpgmath comes in three variants (precise, relaxed and fast). So far, only the precise version is used for intrinsic function folding in f18. It guarantees the greatest numerical precision.

Intrinsic Functions with Missing Folding Support

The following intrinsic functions are allowed in constant expressions but f18 is not yet able to fold them. Note that there might be constraints on the arguments so that these intrinsics can be used in constant expressions (see section 10.1.12 of Fortran 2018 standard).

ALL, ACHAR, ADJUSTL, ADJUSTR, ANINT, ANY, BESSEL_JN (transformational only), BESSEL_YN (transformational only), BTEST, CEILING, CHAR, COUNT, CSHIFT, DOT_PRODUCT, DIM (REAL only), DOT_PRODUCT, EOSHIFT, FINDLOC, FLOOR, FRACTION, HUGE, IACHAR, IALL, IANY, IPARITY, IBITS, ICHAR, IMAGE_STATUS, INDEX, ISHFTC, IS_IOSTAT_END, IS_IOSTAT_EOR, LBOUND, LEN_TRIM, LGE, LGT, LLE, LLT, LOGICAL, MATMUL, MAX, MAXLOC, MAXVAL, MERGE, MIN, MINLOC, MINVAL, MOD (INTEGER only), MODULO, NEAREST, NINT, NORM2, NOT, OUT_OF_RANGE, PACK, PARITY, PRODUCT, REPEAT, REDUCE, RESHAPE, RRSPACING, SCAN, SCALE, SELECTED_CHAR_KIND, SELECTED_INT_KIND, SELECTED_REAL_KIND, SET_EXPONENT, SHAPE, SIGN, SIZE, SPACING, SPREAD, SUM, TINY, TRANSFER, TRANSPOSE, TRIM, UBOUND, UNPACK, VERIFY.

Coarray, non standard, IEEE and ISO_C_BINDINGS intrinsic functions that can be used in constant expressions have currently no folding support at all.

Standard Intrinsics: EXECUTE_COMMAND_LINE

Usage and Info

  • Standard: Fortran 2008 and later, specified in subclause 16.9.73

  • Class: Subroutine

  • Syntax: CALL EXECUTE_COMMAND_LINE(COMMAND [, WAIT, EXITSTAT, CMDSTAT, CMDMSG ])

  • Arguments:

Argument

Description

COMMAND

Shall be a default CHARACTER scalar.

WAIT

(Optional) Shall be a default LOGICAL scalar.

EXITSTAT

(Optional) Shall be an INTEGER with kind greater than or equal to 4.

CMDSTAT

(Optional) Shall be an INTEGER with kind greater than or equal to 2.

CMDMSG

(Optional) Shall be a CHARACTER scalar of the default kind.

Implementation Specifics

COMMAND:
  • Must be preset.

WAIT:
  • If set to false, the command is executed asynchronously.

  • If not preset or set to true, it is executed synchronously.

  • Synchronous execution is achieved by passing the command into std::system on all systems.

  • Asynchronous execution is achieved by calling fork() on POSIX-compatible systems or CreateProcess() on Windows.

EXITSTAT:
  • Synchronous execution:

    • Inferred by the return value of std::system(cmd).

      • On POSIX-compatible systems: return value is first passed into WEXITSTATUS(status), then assigned to EXITSTAT.

      • On Windows, the value is directly assigned as the return value of std::system().

  • Asynchronous execution:

    • Value is not modified.

CMDSTAT:
  • Synchronous execution:

    • -2: ASYNC_NO_SUPPORT_ERR - No error condition occurs, but WAIT is present with the value false, and the processor does not support asynchronous execution.

    • -1: NO_SUPPORT_ERR - The processor does not support command line execution. (system returns -1 with errno ENOENT)

    • 0: CMD_EXECUTED - Command executed with no error.

    • + (positive value): An error condition occurs.

      • 1: FORK_ERR - Fork Error (occurs only on POSIX-compatible systems).

      • 2: EXECL_ERR - Execution Error (system returns -1 with other errno).

      • 3: COMMAND_EXECUTION_ERR - Invalid Command Error (exit code 1).

      • 4: COMMAND_CANNOT_EXECUTE_ERR - Command Cannot Execute Error (Linux exit code 126).

      • 5: COMMAND_NOT_FOUND_ERR - Command Not Found Error (Linux exit code 127).

      • 6: INVALID_CL_ERR - Invalid Command Line Error (covers all other non-zero exit codes).

      • 7: SIGNAL_ERR - Signal error (either stopped or killed by signal, occurs only on POSIX-compatible systems).

  • Asynchronous execution:

    • 0 will always be assigned.

CMDMSG:
  • Synchronous execution:

    • If an error condition occurs, it is assigned an explanatory message; otherwise, it remains unchanged.

    • If a condition occurs that would assign a nonzero value to CMDSTAT but the CMDSTAT variable is not present, error termination is initiated (applies to both POSIX-compatible systems and Windows).

  • Asynchronous execution:

    • The value is unchanged.

    • If a condition occurs that would assign a nonzero value to CMDSTAT but the CMDSTAT variable is not present, error termination is initiated.

      • On POSIX-compatible systems, the child process (async process) will be terminated with no effect on the parent process (continues).

      • On Windows, error termination is not initiated.

Non-Standard Intrinsics: ETIME

Description

ETIME(VALUES, TIME) returns the number of seconds of runtime since the start of the process’s execution in TIME. VALUES returns the user and system components of this time in VALUES(1) and VALUES(2) respectively. TIME is equal to VALUES(1) + VALUES(2).

On some systems, the underlying timings are represented using types with sufficiently small limits that overflows (wrap around) are possible, such as 32-bit types. Therefore, the values returned by this intrinsic might be, or become, negative, or numerically less than previous values, during a single run of the compiled program.

This intrinsic is provided in both subroutine and function forms; however, only one form can be used in any given program unit.

VALUES and TIME are INTENT(OUT) and provide the following:

VALUES(1)

User time in seconds.

VALUES(2)

System time in seconds.

TIME

Run time since start in seconds.

Usage and Info

  • Standard: GNU extension

  • Class: Subroutine, function

  • Syntax: CALL ETIME(VALUES, TIME)

  • Arguments:

  • Return value Elapsed time in seconds since the start of program execution.

Argument

Description

VALUES

The type shall be REAL(4), DIMENSION(2).

TIME

The type shall be REAL(4).

Example

Here is an example usage from Gfortran ETIME

program test_etime
    integer(8) :: i, j
    real, dimension(2) :: tarray
    real :: result
    call ETIME(tarray, result)
    print *, result
    print *, tarray(1)
    print *, tarray(2)   
    do i=1,100000000    ! Just a delay
        j = i * i - i
    end do
    call ETIME(tarray, result)
    print *, result
    print *, tarray(1)
    print *, tarray(2)
end program test_etime

Non-Standard Intrinsics: GETCWD

Description

GETCWD(C, STATUS) returns current working directory.

This intrinsic is provided in both subroutine and function forms; however, only one form can be used in any given program unit.

C and STATUS are INTENT(OUT) and provide the following:

C

Current work directory. The type shall be CHARACTER and of default kind.

STATUS

(Optional) Status flag. Returns 0 on success, a system specific and nonzero error code otherwise. The type shall be INTEGER and of a kind greater or equal to 4.

Usage and Info

  • Standard: GNU extension

  • Class: Subroutine, function

  • Syntax: CALL GETCWD(C, STATUS), STATUS = GETCWD(C)

Example

PROGRAM example_getcwd
  CHARACTER(len=255) :: cwd
  INTEGER :: status
  CALL getcwd(cwd, status)
  PRINT *, cwd
  PRINT *, status
END PROGRAM

Non-standard Intrinsics: RENAME

RENAME(OLD, NEW[, STATUS]) renames/moves a file on the filesystem.

This intrinsic is provided in both subroutine and function form; however, only one form can be used in any given program unit.

Usage and Info

  • Standard: GNU extension

  • Class: Subroutine, function

  • Syntax: CALL RENAME(SRC, DST[, STATUS])

  • Arguments:

  • Return value status code (0: success, non-zero for errors)

Argument

Description

SRC

Source path

DST

Destination path

STATUS

Status code (for subroutine form)

The status code returned by both the subroutine and function form corresponds to the value of errno if the invocation of rename(2) was not successful.

Example

Function form:

program rename_func
    implicit none
    integer :: status
    status = rename('src', 'dst')
    print *, 'status:', status
    status = rename('dst', 'src')
    print *, 'status:', status
end program rename_func

Subroutine form:

program rename_proc
    implicit none
    integer :: status
    call rename('src', 'dst', status)
    print *, 'status:', status
    call rename('dst', 'src')
end program rename_proc

Non-standard Intrinsics: SECOND

This intrinsic is an alias for CPU_TIME: supporting both a subroutine and a function form.

Non-standard Intrinsics: LNBLNK

This intrinsic is an alias for LEN_TRIM, without the optional KIND argument.

Usage and Info

  • Standard: GNU extension

  • Class: Subroutine, function

  • Syntax: CALL SECOND(TIME) or TIME = SECOND()

  • Arguments: TIME - a REAL value into which the elapsed CPU time in seconds is written

  • RETURN value: same as TIME argument