APPENDIX 5
Intrinsic functions in Fortran 90
There is a large a number of intrinsic functions and five intrinsic
subroutinesin Fortran 90. I treat the numeric and mathematical
routines very shortly, since they are not changed from Fortran 77
and therefore should be well-known.
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.
The following are available from Fortran 77: ABS, AIMAG, AINT,
ANINT, CMPLX, CONJG, DBLE, DIM, DPROD, INT, MAX, MIN, MOD, NINT, REAL
and SIGN.
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 -3
The following functions from Fortran 77 can use a kind-parameter like
in AINT(A, kind), namely AINT, ANINT, CMPLX, INT, NINT
and REAL.
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 precision, I for integers, and
R for floating point values in single precision.
Function Generic Specific Data type
name name Arg Res
Conversion 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
Truncation is towards zero, INT(-3.7) becomes -3,
but rounding is correct, NINT(-3.7) becomes -4.
The new functions FLOOR and CEILING truncate towards
minus and plus infinity, respectively.
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.
Same as in Fortran 77. All trigonometric functions work in radians.
The following are available: ACOS, ASIN, ATAN, ATAN2, COS, COSH,
EXP, LOG, LOG10, SIN, SINH, SQRT, TAN and TANH.
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 precision, I for integers,
and R for floating point values in single precision.
Function Generic Specific Data type
name name Arg Res
Square 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 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 as SQRT(4),
but instead you can use NINT(SQRT(REAL(4))). Please also
note that all complex functions return the principal value.
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 CLOG must be different from zero.
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, pi]. 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.
The functions below perform operations from and to character strings.
Please note that ACHAR works with the standard ASCII character
set while CHAR works with the representation in the computer
you are using.
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!
LEN(STRING) returns the length of a character string. There
does not have to be assigned a value to the variable STRING.
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 INTEGER, REAL, COMPLEX, LOGICAL or CHARACTER.
The argument X does not have to be assigned any value. The
second returns an integer kind with the requested number of digits,
and the third returns the kind for floating-point numbers with numerical
precision at least P digits and one decimal exponent range
between -R and +R. The parameters P and
R must be scalar integers. At least one of P and
R must be given.
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.
LOGICAL(L, kind) converts between different kinds of logical
variables. Logical variables can be implemented in various ways, for
example with a physical representation occupying one bit (not recommended),
one byte, one word or perhaps even one double word. This difference
is important if COMMON and EQUIVALENCE with logical
variables have been misused in a program in the traditional way of
Fortran 66 programming.
8. Numerical inquiry functions:
These functions work with a certain model of integer and floating-point
arithmetics, see ISO (1991), section 13.7.1. The functions return
properties of numbers of the same kind as the variable X,
which can be real and in some cases integer. Functions that return
properties of the actual argument X are available in section
12 below, floating-point manipulation functions.
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
BIT_SIZE(I) returns the number of bits according to the
model of bit representation in the standard ISO (1991), section 13.5.7.
Normally we get the number of bits in a (whole) word.
The model for bit representation in the standard ISO (1991), section
13.5.7 is used.
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
TRANSFER(SOURCE, MOULD, size) specifies that the physical
representation of the first argument SOURCE shall be treated
as if it had type and parameters as the second argument MOULD,
but without converting it. The purpose is to give a possibility to
move a quantity of a certain type via a routine that does not have
exactly that data type.
12. Floating-point manipulation functions:
These functions work in a certain model of integer and floating-point
arithmetic, see the standard ISO(1991), section 13.7.1. The functions
return numbers related to the actual variable X of the type
REAL. Functions that return properties for the numbers of
the same kind as the variable X are under section
8 (Numerical inquiry functions).
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
DOT_PRODUCT(VECTOR_A, VECTOR_B) makes a scalar product of
two vectors, which must have the same length (same number of elements).
Please note that if VECTOR_A is of type COMPLEX
the result is SUM(CONJG(VECTOR_A)*VECTOR_B).
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.
14. Array functions:
ALL(MASK, dim) returns a logical value that indicates
whether all relations in MASK are .TRUE., along
only the desired dimension if the second argument is given.
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.
MERGE(TSOURCE, FSOURCE, MASK) is a function which joins
two arrays. It gives the elements in TSOURCE if the condition
in MASK is .TRUE. and FSOURCE if the
condition in MASK is .FALSE. The two fields TSOURCE
and FSOURCE have to be of the same type and the same
shape. The result is also of this type and this shape. Also MASK
must have the same shape.
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_L_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_ARRAY
The 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
PACK(ARRAY, MASK, vector) packs an array to a vector with
the control of MASK. The shape of the logical array MASK
has to agree with the one for ARRAY or MASK
must be a scalar. If VECTOR is included, it has to be an
array of rank 1 (i.e. a vector) with at least as many elements as
those that are true in MASK and have the same type as ARRAY.
If MASK is a scalar with the value .TRUE. then
VECTOR instead must have the same number of elements as
ARRAY.
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 fulfill 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
SPREAD(SOURCE, DIM, NCOPIES) returns an array of the same
type as the argument SOURCE with the rank increased by one.
The parameters DIM and NCOPIES are integer. If
NCOPIES is negative the value zero is used instead. If SOURCE
is a scalar, then SPREAD becomes a vector with NCOPIES
elements that all have the same value as SOURCE. The
parameter DIM indicates which index is to be extended. It
has to be within the range 1 and 1+(rank of SOURCE),
if SOURCE is a scalar then DIM has to be one.
The parameter NCOPIES is the number of elements in the new
dimensions. Additional discussion is given in the solution to exercise
(11.1).
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.
RESHAPE(SOURCE, SHAPE, pad, order) constructs an array with
a specified shape SHAPE starting from the elements in a
given array SOURCE. If PAD is not included then
the size of SOURCE has to be at least PRODUCT (SHAPE).
If PAD is included it has to have the same type as SOURCE.
If ORDER is included, it has to be an INTEGER
array with the same shape as SHAPE and the values must be
a permutation of (1,2,3,...,N), where N is the number of elements
in SHAPE , it has to be less than, or equal to 7.
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_MATRIX
The 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
The shift functions return the shape of an array unchanged, but move
the elements. They are rather difficult to explain so I recommend
to study also the standard ISO (1991).
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.0
A simple example of the above two functions in the matrix case follows.
I have here used RESHAPE in order to create a suitable matrix
to start work with. The program is not reproduced here, only the main
statements.
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
TRANSPOSE (MATRIX) transposes a matrix, which is an array
of rank 2. It replaces the rows and columns in the matrix.
MAXLOC(ARRAY, mask) returns the position of the greatest
element in the array ARRAY, if MASK is included
only for those which fulfill the conditions in MASK. The
result is an integer vector! It is used in the solution of
exercise (11.1).
MINLOC(ARRAY, mask) returns the position of the smallest
element in the array ARRAY , if MASK is included
only for those which fulfill the conditions in MASK. The
result is an integer vector!
ASSOCIATED(POINTER, target) is logical function that indicates
if the pointer POINTER is associated with some target, and
if a specific TARGET is included it indicates if it is associated
with exactly that target. If both POINTER and TARGET
are pointers, the result is .TRUE. only if both are
associated with the same target. I refer the reader to chapter
12 of the main text, Pointers.
-
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 8 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.
-
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.
-
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: 25 November 1999
boein@nsc.liu.se |