- Introduction
- 1. Function which determines if a certain argument is in an actual argument list
- 2. Numerical functions
- 3. Mathematical functions
- 4. Character string functions
- 5. Character string function for request
- 6. Kind functions
- 7. Logical function
- 8. Numerical inquiry functions
- 9. Bit inquiry function
- 10. Bit manipulation functions
- 11. Transfer functions
- 12. Floating-point manipulation functions
- 13. Vector- and matrix-multiplication functions
- 14. Array functions
- 15. Array inquiry functions
- 16. Array construct functions
- 17. ARRAY reshape function
- 18. ARRAY manipulation functions
- 19. Array location functions
- 20. Pointer inquiry functions
- 21. Intrinsic subroutines

This section is based on section 13 of the ISO standard (1991), which contains a more formal treatment. We follow the arrangement of the different functions and subroutines in the standard, but explain directly in the list. For a more detailed treatment we refer to Metcalf and Reid (1990, 1993).

When a parameter below is optional it is given in lower case characters. When an argument list contains several arguments the function can be called either by position related arguments or by a keyword. Keyword must be used if some previous argument is not included. Keywords are normally the names that are given below.

We have not always given all the natural limitations to the variables, for example that the rank is not permitted to be negative.

The function `PRESENT(A) `
returns `.TRUE. ` if the argument `A ` is in the calling list,
`.FALSE. ` in
the other case. The use is illustrated in the example program in
chapter 8 of the main text.

In addition, `CEILING, FLOOR ` and `MODULO ` have been added to Fortran
90. Only the last one is difficult to explain, which is most easily
done with the examples from ISO (1991)

MOD (8,5) gives 3 MODULO (8,5) gives 3 MOD (-8,5) gives -3 MODULO (-8,5) gives 2 MOD (8,-5) gives 3 MODULO (8,-5) gives -2 MOD (-8,-5) gives -3 MODULO (-8,-5) gives -3The following functions from Fortran 77 can use a kind-parameter like in

A historic fact is that the numerical functions in Fortran 66 had to have specific (different) names in different precisions, and these explicit names are still the only ones which can be used when a function name is passed as an argument.

A complete table of all the numerical functions follow. Those names that
are indicated with a star * are not permitted to be used as arguments.
Some functions, like `INT ` and `IFIX ` have
two specific names, either can be used. On the other hand, some functions do not have any specific name.
Below I use `C ` for complex floating point values,
`D ` for floating point values in double precion,
`I ` for integers, and
`R ` for floating point values in single precion.

Truncation is towards zero,Function Generic Specific Data type name name Arg ResConversion INT - I I to integer * INT R I * IFIX R I * IDINT D I (of the real part) - C I Conversion REAL * REAL I R to real * FLOAT I R - R R * SNGL D R (real part) - C R Conversion DBLE - I D to double - R D precision - D D (real part) - C D Conversion CMPLX - I (2I) C to complex - R (2R) C - D (2D) C - C C Truncation AINT AINT R R DINT D D Rounding ANINT ANINT R R DNINT D D NINT NINT R I IDNINT D I Absolute ABS IABS I I value ABS R R DABS D D CABS C R Remainder MOD MOD 2I I AMOD 2R R DMOD 2D D MODULO - 2I I - 2R R - 2D D Floor FLOOR - I I - R R - D D Ceiling CEILING - I I - R R - D D Transfer SIGN ISIGN 2I I of sign SIGN 2R R DSIGN 2D D Positive DIM IDIM 2I I difference DIM 2R R DDIM 2D D Inner product - DPROD R D Maximum MAX * MAX0 I I * AMAX1 R R * DMAX1 D D - * AMAX0 I R - * MAX1 R I Minimum MIN * MIN0 I I * AMIN1 R R * DMIN1 D D - * AMIN0 I R - * MIN1 R I Imaginary part - AIMAG C R Conjugate - CONJG C C

The function `CMPLX ` can have one or two arguments, if two arguments
are present
these must be of the same type but not `COMPLEX`.

The function `MOD(X,Y) ` calculates `X - INT(X/Y)*Y`.

The sign transfer function `SIGN(X,Y) ` takes the sign of the second
argument and puts it on the first argument,
`ABS(X) ` if `Y >= 0 ` and `-ABS(X) `
if `Y < 0`.

Positive difference `DIM ` is a function I have never used,
but `DIM(X,Y) ` gives `X-Y ` if this is positive and zero
in the other case.

Inner product `DPROD ` on the other hand is a very useful
function which gives the product of two numbers in single precision
as a double precision number.
It is both fast and accurate.

The two functions `MAX ` and `MIN ` are unique in that they may have
an arbitrary number of arguments, but at least two. The arguments have to be
of the same type, but are not permitted to be of type `COMPLEX`.

A historic fact is that the mathematical functions in Fortran 66 had to have specific (different) names in different precisions, and these explicit names are still the only ones which can be used when a function name is passed as an argument.

A complete table of all the mathematical functions follow.
Below I use `C` for complex floating point values,
`D` for floating point values in double precion,
`I` for integers, and
`R` for floating point values in single precion.

The purpose of most of these functions is obvious. Note that they are all only defined for floating point numbers, and not for integers. You can therefore not calculate the square root of 4 asFunction Generic Specific Data type name name Arg ResSquare root SQRT SQRT R R DSQRT D D CSQRT C C Exponential EXP EXP R R DEXP D D CEXP C C Natural LOG ALOG R R logarithm DLOG D D CLOG C C Common LOG10 ALOG10 R R logarithm DLOG10 D D Sine SIN SIN R R DSIN D D CSIN C C Cosine COS COS R R DCOS D D CCOS C C Tangent TAN TAN R R DTAN D D Arcsine ASIN ASIN R R DASIN D D Arccosine ACOS ACOS R R DCOS D D Arctangent ATAN ATAN R R DATAN D D ATAN2 ATAN2 2R R DATAN2 2D D Hyperbolic SINH SINH R R sine DSINH D D Hyperbolic COSH COSH R R cosine DCOSH D D Hyperbolic TANH TANH R R tangent DTANH D D

The square root gives a real result for a real argument
in single or double precision, and a complex result for a
complex argument. So `SQRT(-1.0) ` gives an error message (usually already at
compile time), while you can get the complex square root
using the following statements.

COMPLEX, PARAMETER :: MINUS_ONE = -1.0 COMPLEX :: Z Z = SQRT(MINUS_ONE)The argument for the usual logarithms has to be positive, while the argument for

The modulus for the argument to `ASIN ` and `ACOS ` has to be
at most 1. The result will be within [-pi/2, pi/2] and [0, pi], respectively.

The function `ATAN ` will return a value in [-pi/2, pi/2].

The function `ATAN2(Y,X) = arctan(y,x) ` will return a value in (-pi/2, pi/2].
If `Y ` is positive the result will be positive.
If `Y ` is zero the result will be zero if `X ` is positive,
and pi if `X ` is negative.
If `Y ` is negative the result will be negative.
If `X ` is zero the result will be plus or minus pi/2.
Both `X ` and `Y ` are not permitted to be zero simultaneously.
The purpose of the function is to avoid division by zero.

A natural limitation for the mathematical functions is the limited accuracy and range,
which means that for example `EXP ` can cause underflow or overflow at
rather common values of the argument. The trigonometric functions will get very
low accuracy for large arguments.
These limitations are implementation dependent,
and should be given in the vendor's manual.

ACHAR(I) Returns the ASCII character which has number I ADJUSTL(STRING) Adjusts to the left ADJUSTR(STRING) Adjusts to the right CHAR(I, kind) Returns the character that has the number I IACHAR(C) Returns the ASCII number of the character C ICHAR(C) Returns the number of character C INDEX(STRING, SUBSTRING, back) Returns the starting position for a substring within a string. If BACK is true then you get the last starting position, in the other case, the first one. LEN_TRIM(STRING) Returns the length of the string without the possibly trailing blanks. LGE(STRING_A, STRING_B) LGT(STRING-A, STRING_B) LLE(STRING_A, STRING_B) LLT(STRING_A, STRING_B)The above routines compare two strings using sorting according to ASCII. If a string is shorter than the other, blanks are added at the end of the short string. If a string contains a character outside the ASCII character set, the result is implementation-dependent.

REPEAT(STRING, NCOPIES) Concatenates a character string NCOPIES times with itself. SCAN(STRING, SET, back) Returns the position of the first occurrence of any character in the string SET in the string STRING. If BACK is true, you will get the rightmost such character. TRIM(STRING) Returns the character string STRING without trailing blanks. VERIFY(STRING, SET, back) Returns the position of the first character in STRING which is not in SET. If BACK is TRUE, you get the last one! The result is zero if all characters are included!

KIND(X) SELECTED_INT_KIND(R) SELECTED_REAL_KIND(p, r)The first returns the kind of the actual argument, which can be of the type

The result of `SELECTED_INT_KIND ` is an integer from zero and upward,
if the desired kind is not available you will get -1. If several
implemented types satisfy the condition, the one with the least
decimal range is used. If there still are several types or kinds that
satisfy the condition, the one with the smallest kind number will be
used.

The result of `SELECTED_REAL_KIND ` is also an integer from zero and
upward; if the desired kind is not available, then -1 is returned if
the precision is not available, -2 if the exponent range is not
available and -3 if no one of the requirements are available. If
several implemented types satisfy the condition, the one with the
least decimal precision is returned, and if there are several of
them, the one with the least kind number is returned.

Examples are given in chapter 2 of the main text. Examples of kinds in a few different implementations (NAG and Cray) are given in Appendix 6.

DIGITS(X) The number of significant digits EPSILON(X) The least positive number that added to 1 returns a number that is greater than 1 HUGE(X) The largest positive number MAXEXPONENT(X) The largest exponent MINEXPONENT The smallest exponent PRECISION(X) The decimal precision RADIX(X) The base in the model RANGE(X) The decimal exponent TINY(X) The smallest positive number

BTEST(I, POS) .TRUE. if the position number POS of I is 1 IAND(I, J) logical addition of the bit characters in variables I and J IBCLR(I, POS) puts a zero in the bit in position POS IBITS(I, POS, LEN) uses LEN bits of the word I with beginning in position POS, the additional bits are set to zero. It requires that POS + LEN <= BIT_SIZE(I) IBSET(I, POS) puts the bit in position POS to 1 IEOR(I, J) performs logical exclusive OR IOR(I, J) performs logical OR ISHIFT(I, SHIFT) performs logical shift (to the right if the number of steps SHIFT < 0 and to the left if SHIFT > 0). Positions that are vacated are set to zero. ISHIFTC(I, SHIFT, size) performs logical shift a number of steps circularly to the right if SHIFT < 0, circularly to the left if SHIFT > 0. If SIZE is given, it is required that 0 < SIZE <= BIT_SIZE(I). Shift is only done for the bits that are in the SIZE rightmost positions, but for all positions if SIZE is not given. NOT(I) returns a logical complement

EXPONENT(X) exponent of the number FRACTION(X) the fractional part of the number NEAREST(X, S) returns the next representable number in the direction of the sign of S RRSPACING(X) returns the inverted value of the distance between the two nearest possible numbers SCALE(X, I) multiplies X by the base to the power I SET_EXPONENT(X, I) returns the number that has the fractional part of X and the exponent I SPACING(X) the distance between the two nearest possible numbers

`MATMUL(MATRIX_A, MATRIX_B) `
makes the matrix product of two matrices, which must be consistent,
i.e. have the dimensions like `(M, K) ` and `(K, N)`. Used
in chapter 11 of the main text.

`ANY(MASK, dim) `
returns a logical value that indicates whether any relation in `MASK `
is `.TRUE.`, along only the desired dimension if the second argument is
given.

`COUNT(MASK, dim) `
returns a numerical value that is the number of relations in `MASK `
who are `.TRUE.`, along only the desired dimension if the second argument is
given.

`MAXVAL(ARRAY, dim, mask) `
returns the largest value in the array `ARRAY`, of those that obey
the relation in the third argument `MASK ` if that one is given, along
only the desired dimension if the second argument `DIM ` is given.

`MINVAL(ARRAY, dim, mask) `
returns the smallest value in the array `ARRAY`, of those that obey
the relation in the third argument `MASK ` if that one is given, along
only the desired dimension if the second argument `DIM ` is given.

`PRODUCT(ARRAY, dim, mask) `
returns the product of all the elements in the array `ARRAY`, of
those that obey the relation in the third argument `MASK ` if that one is
given, along only the desired dimension if the second argument `DIM ` is
given.

`SUM (ARRAY, dim, mask) `
returns the sum of all the elements in the array `ARRAY`, of
those that obey the relation in the third argument `MASK ` if that one is
given, along only the desired dimension if the second argument `DIM ` is
given. An example is given in Appendix 3, section 10.

See also Appendix 3, section 10.

`ALLOCATED(ARRAY) ` is a
logical function which indicates if the array is allocated.

`LBOUND(ARRAY, dim) ` is a
function which returns the lower dimension limit for the `ARRAY`. If
`DIM ` (the dimension) is not given as an argument, you get an integer
vector, if `DIM ` is included, you get the integer value with exactly
that lower dimension limit, for which you asked.

`SHAPE(SOURCE) ` is a
function which returns the shape of an array `SOURCE` as an integer
vector.

`SIZE(ARRAY, dim) ` is a
function which returns the number of elements in an array `ARRAY`, if
`DIM ` is not given, and the number of elements in the relevant dimension
if `DIM ` is included.

`UBOUND(ARRAY, dim) ` is a
function similar to `LBOUND ` which returns the upper dimensional
limits.

I here give a rather complete example of the use of `MERGE ` which
also uses `RESHAPE ` from the next section in order to build suitable
test matrices.

Note that the two subroutines `WRITE_ARRAY `
and `WRITE_L_ARRAY ` are
test routines to write matrices which in the first case are of
a `REAL `
type, in the second case of a `LOGICAL ` type.

IMPLICIT NONE INTERFACE SUBROUTINE WRITE_ARRAY (A) REAL :: A(:,:) END SUBROUTINE WRITE_ARRAY SUBROUTINE WRITE_L_ARRAY (A) LOGICAL :: A(:,:) END SUBROUTINE WRITE_L_ARRAY END INTERFACE REAL, DIMENSION(2,3) :: TSOURCE, FSOURCE, RESULT LOGICAL, DIMENSION(2,3) :: MASK TSOURCE = RESHAPE( (/ 11, 21, 12, 22, 13, 23 /), & (/ 2, 3 /) ) FSOURCE = RESHAPE( (/ -11, -21, -12, -22, -13, -23 /), & (/ 2,3 /) ) MASK = RESHAPE( (/ .TRUE., .FALSE., .FALSE., .TRUE., & .FALSE., .FALSE. /), (/ 2,3 /) ) RESULT = MERGE(TSOURCE, FSOURCE, MASK) CALL WRITE_ARRAY(TSOURCE) CALL WRITE_ARRAY(FSOURCE) CALL WRITE_ARRAY(MASK) CALL WRITE_ARRAY(RESULT) END SUBROUTINE WRITE_ARRAY (A) REAL :: A(:,:) DO I = LBOUND(A,1), UBOUND(A,1) WRITE(*,*) (A(I, J), J = LBOUND(A,2), UBOUND(A,2) ) END DO RETURN END SUBROUTINE WRITE_ARRAY SUBROUTINE WRITE_L_ARRAY (A) LOGICAL :: A(:,:) DO I = LBOUND(A,1), UBOUND(A,1) WRITE(*,"(8L12)") (A(I, J), J= LBOUND(A,2), UBOUND(A,2)) END DO RETURN END SUBROUTINE WRITE_L_ARRAYThe following output is obtained

11.0000000 12.0000000 13.0000000 21.0000000 22.0000000 23.0000000 -11.0000000 -12.0000000 -13.0000000 -21.0000000 -22.0000000 -23.0000000 T F F F T F 11.0000000 -12.0000000 -13.0000000 -21.0000000 22.0000000 -23.0000000

The result is a vector with as many elements as those
in `ARRAY ` that
obey the conditions if `VECTOR ` is not included
(i.e. all elements if
`MASK ` is a scalar with value `.TRUE.`). In the other case the number of
elements of the result will be as many as in `VECTOR`. The values will
be the approved ones, i.e. the values which fulfil the condition, and
will be in the ordinary Fortran order. If `VECTOR ` is included and the
number of its elements exceeds the number of approved values, the
lacking values required for the result are taken from the
corresponding locations in `VECTOR`.

The following example is based on the modification of the one for
`MERGE `, but I give now only the results.

ARRAY 11.0000000 12.0000000 13.0000000 21.0000000 22.0000000 23.0000000 VECTOR -11.0000000 -21.0000000 -12.0000000 -22.0000000 -13.0000000 -23.0000000 MASK T F F F T F PACK(ARRAY, MASK) 11.0000000 22.0000000 PACK(ARRAY, MASK, VECTOR) 11.0000000 22.0000000 -12.0000000 -22.0000000 -13.0000000 -23.0000000

`UNPACK(VECTOR, MASK, ARRAY) ` scatters a vector to an
array under control of `MASK`.
The shape of the logical array `MASK ` has to agree with the one for
`ARRAY`. The array `VECTOR ` has to have the rank 1
(i.e. it is a vector)
with at least as many elements as those that are true in `MASK`, and
also has to have the same type as `ARRAY`. If `ARRAY ` is given as a
scalar then it is considered to be an array with the same shape as
`MASK ` and the same scalar elements everywhere.

The result will be an array with the same shape as `MASK ` and the
same type as `VECTOR`. The values will be those from `VECTOR `
that are
accepted (i.e. those fulfilling the condition in `MASK`), taken in the
ordinary Fortran order, while in the remaining positions in `ARRAY ` the
old values are kept.

The result has of course a shape `SHAPE ` and the elements are those
in `SOURCE`, possibly complemented with `PAD`. The different dimensions
have been permuted at the assignment of the elements if `ORDER ` was
included, but without influencing the shape of the result.

A few simple examples are given in the previous and the next section and also in Appendix 3, section 9. A more complicated example, illustrating also the optional arguments, follows.

! PROGRAM TO TEST THE OPTIONAL ARGUMENTS TO RESHAPE INTERFACE SUBROUTINE WRITE_MATRIX(A) REAL, DIMENSION(:,:) :: A END SUBROUTINE WRITE_MATRIX END INTERFACE REAL, DIMENSION (1:9) :: B = (/ 11, 12, 13, 14, 15, 16, 17, 18, 19 /) REAL, DIMENSION (1:3, 1:3) :: C, D, E REAL, DIMENSION (1:4, 1:4) :: F, G, H INTEGER, DIMENSION (1:2) :: ORDER1 = (/ 1, 2 /) INTEGER, DIMENSION (1:2) :: ORDER2 = (/ 2, 1 /) REAL, DIMENSION (1:16) :: PAD1 = (/ -1, -2, -3, -4, -5, -6, -7, -8, & & -9, -10, -11, -12, -13, -14, -15, -16 /) C = RESHAPE( B, (/ 3, 3 /) ) CALL WRITE_MATRIX(C) D = RESHAPE( B, (/ 3, 3 /), ORDER = ORDER1) CALL WRITE_MATRIX(D) E = RESHAPE( B, (/ 3, 3 /), ORDER = ORDER2) CALL WRITE_MATRIX(E) F = RESHAPE( B, (/ 4, 4 /), PAD = PAD1) CALL WRITE_MATRIX(F) G = RESHAPE( B, (/ 4, 4 /), PAD = PAD1, ORDER = ORDER1) CALL WRITE_MATRIX(G) H = RESHAPE( B, (/ 4, 4 /), PAD = PAD1, ORDER = ORDER2) CALL WRITE_MATRIX(H) END SUBROUTINE WRITE_MATRIX(A) REAL, DIMENSION(:,:) :: A WRITE(*,*) DO I = LBOUND(A,1), UBOUND(A,1) WRITE(*,*) (A(I,J), J = LBOUND(A,2), UBOUND(A,2)) END DO END SUBROUTINE WRITE_MATRIXThe output from the above program is as follows.

11.0000000 14.0000000 17.0000000 12.0000000 15.0000000 18.0000000 13.0000000 16.0000000 19.0000000 11.0000000 14.0000000 17.0000000 12.0000000 15.0000000 18.0000000 13.0000000 16.0000000 19.0000000 11.0000000 12.0000000 13.0000000 14.0000000 15.0000000 16.0000000 17.0000000 18.0000000 19.0000000 11.0000000 15.0000000 19.0000000 -4.0000000 12.0000000 16.0000000 -1.0000000 -5.0000000 13.0000000 17.0000000 -2.0000000 -6.0000000 14.0000000 18.0000000 -3.0000000 -7.0000000 11.0000000 15.0000000 19.0000000 -4.0000000 12.0000000 16.0000000 -1.0000000 -5.0000000 13.0000000 17.0000000 -2.0000000 -6.0000000 14.0000000 18.0000000 -3.0000000 -7.0000000 11.0000000 12.0000000 13.0000000 14.0000000 15.0000000 16.0000000 17.0000000 18.0000000 19.0000000 -1.0000000 -2.0000000 -3.0000000 -4.0000000 -5.0000000 -6.0000000 -7.0000000

`CSHIFT(ARRAY, SHIFT, dim) `
performs circular shift by `SHIFT ` positions to the left if
`SHIFT ` is
positive and to the right if it is negative. If `ARRAY ` is a vector the
shift is being done in a natural way, if it is an array of a higher
rank then the shift is in all sections along the dimension `DIM`. If
`DIM ` is missing
it is considered to be 1, in other cases it has to be a scalar integer
number between 1 and `n ` (where n equals the rank of `ARRAY `). The
argument `SHIFT ` is a scalar integer or an integer array of rank `n-1` and
the same shape as the `ARRAY`, except along the dimension `DIM ` (which is
removed because of the lower rank). Different sections can therefore
be shifted in various directions and with various numbers of
positions.

`EOSHIFT(ARRAY, SHIFT, boundary, dim) `
performs shift to the left if `SHIFT ` is positive and to
the right if
it is negative. Instead of the elements shifted out new elements are
taken from `BOUNDARY`. If `ARRAY ` is a vector the shift is being done in
a natural way, if it is an array of a higher rank, the shift on all
sections is along the dimension `DIM`. If `DIM ` is missing, it is
considered to be 1, in other cases it has to have a scalar integer
value between 1 and `n ` (where `n ` equals the rank of `ARRAY`). The
argument `SHIFT ` is a scalar integer if `ARRAY ` has rank 1, in the other
case it can be a scalar integer or an integer array of rank `n-1 ` and
with the same shape as the array `ARRAY ` except along the
dimension `DIM `
(which is removed because of the lower rank).

The corresponding
applies to `BOUNDARY ` which has to have the same type as the `ARRAY`. If
the parameter `BOUNDARY ` is missing you have the choice of values zero,
`.FALSE. ` or blank being used, depending on the data type. Different
sections can thus be shifted in various directions and with various
numbers of positions.
A simple example of the above two functions for the vector case
follows, both the program and the output.

REAL, DIMENSION(1:6) :: A = (/ 11.0, 12.0, 13.0, 14.0, & 15.0, 16.0 /) REAL, DIMENSION(1:6) :: X, Y WRITE(*,10) A X = CSHIFT ( A, SHIFT = 2) WRITE(*,10) X Y = CSHIFT (A, SHIFT = -2) WRITE(*,10) Y X = EOSHIFT ( A, SHIFT = 2) WRITE(*,10) X Y = EOSHIFT ( A, SHIFT = -2) WRITE(*,10) Y 10 FORMAT(1X,6F6.1) END 11.0 12.0 13.0 14.0 15.0 16.0 13.0 14.0 15.0 16.0 11.0 12.0 15.0 16.0 11.0 12.0 13.0 14.0 13.0 14.0 15.0 16.0 0.0 0.0 0.0 0.0 11.0 12.0 13.0 14.0A simple example of the above two functions in the matrix case follows. I have here used

B = (/ 11.0, 12.0, 13.0, 14.0, 15.0, 16.0 /) 11.0 12.0 13.0 Z = RESHAPE( B, (/3,3/) ) 14.0 15.0 16.0 17.0 18.0 19.0 17.0 18.0 19.0 X = CSHIFT (Z, SHIFT = 2) 11.0 12.0 13.0 14.0 15.0 16.0 13.0 11.0 12.0 X = CSHIFT ( Z, SHIFT = 2, DIM = 2) 16.0 14.0 15.0 19.0 17.0 18.0 14.0 15.0 16.0 X = CSHIFT (Z, SHIFT = -2) 17.0 18.0 19.0 11.0 12.0 13.0 17.0 18.0 19.0 X = EOSHIFT ( Z, SHIFT = 2) 0.0 0.0 0.0 0.0 0.0 0.0 13.0 0.0 0.0 X = EOSHIFT ( Z, SHIFT = 2, DIM = 2) 16.0 0.0 0.0 19.0 0.0 0.0 0.0 0.0 0.0 X = EOSHIFT ( Z, SHIFT = -2) 0.0 0.0 0.0 11.0 12.0 13.0

`MINLOC(ARRAY, mask) `
returns the position of the smallest element in the array `ARRAY `, if
`MASK ` is included only for those which fulfil the conditions in `MASK`.
The result is an integer **vector!**

### Time routines:

DATE_AND_TIME(date, time, zone, values)

A subroutine which returns the date, the time and the time zone. At least one argument has to be given.`DATE`must be a scalar character string variable with at least 8 characters and it is assigned the value`CCYYMMDD`for century, year, month and day. All are given numerically, with blanks if the system does not include the date.`TIME`must also be a scalar character string variable with at least 10 characters and it is assigned a value`hhmmss.sss`for time in hours, minutes, seconds and milliseconds. All are given numerically with blanks if the system does not include a clock.`ZONE`must be a scalar character string variable with at least 5 characters and it is assigned the value`+hhmm`for sign, time in hours and minutes for the local time difference with UTC (which was previously called Greenwich Mean Time). All are given numerically, with blanks if the system does not include a clock. In Sweden we therefore get`+0100`in winter and`+0200`in summer, in Novosibirsk we get`+0700`.The variable

`VALUES`is instead an integer vector with at least 5 elements, it gives the easiest way of using the results from`DATE_AND_TIME`at the calculations in a program. If the system does not include the date or the time you get the value`-HUGE(0)`, that is the smallest integer number in the model, as output. The vector will include the following elements: year, month, day, time difference in minutes, hours, minutes, seconds and milliseconds.SYSTEM_CLOCK(COUNT, COUNT_RATE, COUNT_MAX)

Subroutine which returns the system time. At least one argument has to be given.`COUNT`is a scalar integer which is increased by one for each cycle up to`COUNT_MAX`, where it starts once again. If there is no system clock then`-HUGE(0)`is returned.`COUNT_RATE`is a scalar integer that gives the number of cycles per second. If there is no system clock the value zero is returned.`COUNT_MAX`is a scalar integer which gives the maximum value that`COUNT`can reach. If there is no system clock, zero is returned instead.### Bit copy routine:

MVBITS(FROM, FROMPOS, LEN, TO, TOPOS)

A subroutine which copies the sequence of bits in position`FROMPOS`and has the length`LEN`to target`TO`starting in position`TOPOS`. The remaining bits are not changed. All quantities have to be integers and all except`TO`have to have`INTENT(IN)`while`TO`is supposed to have`INTENT(INOUT)`and be of the same kind type as`FROM`. The same variable can be both`FROM`and`TO`. Some natural restrictions apply to the values of`LEN, FROMPOS`and`TOPOS`and you also have to consider the value of`BIT_SIZE`.### Random number routines:

A sequence of pseudo random numbers can be generated from a starting value which is stored as an integer vector. The subroutines offer a portable interface towards an implementation dependent random number sequence.RANDOM_NUMBER(HARVEST)

This subroutine returns in the floating-point number variable`HARVEST`one (or several if`HARVEST`is an array) random numbers between zero and 1.RANDOM_SEED(size, put, get)

This subroutine resets, or gives information about, the random number generator. No arguments have to be provided. The output variable`SIZE`must be a scalar integer and gives the number of integers`(N)`the processor uses for the starting value. The input variable`PUT`is an integer vector which puts the starting numbers provided by the user into the random number generator. The output variable`GET`(also an integer vector)reads the present starting value. Example:CALL RANDOM_SEED ! Initializing CALL RANDOM SEED (SIZE=K) ! Sets K = N CALL RANDOM_SEED (PUT = SEED (1:K)) ! Uses the starting value ! given by the user CALL RANDOM_SEED (GET = OLD(1:K)) ! Returns the present ! starting value

A simple example on the use of these functions is now available.

Last modified: 6 June 1996