mod(8,3) = 2 , mod(27,4) = 3 , mod(11,2) = 1 , mod(20,5) = 0 .
The main program uses a call statement to call the subroutine. The call statement has also a list of variables, which are substituted for the subroutine variables. The subroutine executes, modifying some or all of its variables, which are then substituted back for the original call variables in the main program. The variables in the call statement must match the variables in the subroutine according to number, type, and dimension. (Oversights lead to type-mismatch error messages by the compiler.)
Here is a simple program named average that prompts the user for two real numbers, calls a subroutine named avg to average the numbers, and then prints the average.
program average real x, y, z print *, "What are the two numbers you want to average?" read *, x, y call avg(x,y,z) print *, "The average is", z end subroutine avg(a,b,c) real a, b, c c = (a + b)/2. endWhen the subroutine is called it substitutes x for a, y for b, and z for c. (Although the user does not input z, GNU Fortran will have given it some default value.) After the subroutine does its calculations, the new values of a, b, c are substituted back into the main program for x, y, z. (In this particular subroutine only c changes, so x and y retain their original values.) After the subroutine completes its run, action is returned to the statement in the main program immediately following the call statement.
Just remember that, except for the first statement naming the subroutine and listing the variables, a subroutine has the same general structure as a main program. It begins with type and dimension statements, has a main body carrying out the action, and concludes with an end statement.
The advantage of using subroutines is that the main program can be kept relatively simple and easy to follow, while nitty-gritty calculations and complex procedures are shuffled off to various subroutines, each performing a specific task. A well-written subroutine can be saved in a subroutine "library", to be inserted into other main programs as the need arises.
A subroutine can call another subroutine, and it can also access a function subprogram.
A subroutine need not depend on any variables - in which case no parentheses follow the subroutine name. Here is a simple subroutine involving no variables:
subroutine bluesky print *, "The sky is blue." endThe call statement for this subroutine,
call blueskylikewise lists no variables.
The following subroutine computes the product of a 2 x 2 matrix A with a 2 x 1 vector x, according to the formula
It accepts as variables a 2 x 2 array A and one-dimensional arrays x and y, each indexed from 1 to 2. The array y represents the product y = Ax.
subroutine prod(A,x,y) real A(2,2), x(2), y(2) y(1) = A(1,1) * x(1) + A(1,2) * x(2) y(2) = A(2,1) * x(1) + A(2,2) * x(2) endA call statement for this subroutine might be something like
where B and u are arrays known to the main program and the product v is to be computed by the subroutine. Of course the main program will have appropriately dimensioned these arrays. After the subroutine completes its task and returns control to the main program, the array v will represent the product Bu.
Here is a subroutine, using a return statement, that decides whether a positive integer n is a prime number:
subroutine check(n,result) integer n, i, root character result*9 if (n .eq. 1) then result = "not prime" return end if root = sqrt(real(n)) do i = 2, root if (mod(n,i) .eq. 0) then result = "not prime" return end if end do result = "prime" endThe subroutine begins by checking whether n = 1, and if true it sets result = "not prime" and returns to the main program. If n > 1 the DO LOOP looks at integers from 2 up to the square root of n, checking whether each is a divisor of n. If and when it finds such a divisor, it sets result = "not prime" and returns to the main program. But if no divisor of n is found, the subroutine completes the entire loop and sets result = "prime". After the subroutine ends, the main program need only look at the value of result to find out whether n is prime or not prime.
Let us assume also that the main program's call statement for this subroutine is
where x, y, and z are variables from the main program. The types and dimensions of x, y, and z will have been declared in the main program, and these must match the types and dimensions of a, b, and c, respectively, as declared in the subroutine.The values of x, y, and z will have been stored by Fortran in certain memory locations, designated in the diagram below as triangles:
|x → Δ|
|y → Δ|
|z → Δ|
When the subroutine "demo" is called, Fortran assigns the variable a the same memory location as x, b the same location as y, and c the same as z:
|x → Δ ← a|
|y → Δ ← b|
|z → Δ ← c|
(This explains why the types and dimensions must match!) Now, as the subroutine "demo" runs, the variables a, b and c might change to new values. But since x, y, and z share memory locations with a, b, and c, the values of x, y, and z of course will have to change simultaneously along with a, b, and c. When the subroutine terminates and returns control to the main program, a, b, and c then are no longer active variables, but x, y, and z retain the final values of a, b, and c at the conclusion of the subroutine.
There is a way to fool Fortran into not changing the value of a calling variable when the subroutine runs. In the above example, suppose we change the call statement to
call demo(x,(y),z) .
When the variable y is enclosed in parentheses, Fortran treats (y) as a new expression and assigns it a different memory location than that of y, but with the save value as y. The last diagram changes to
|x → Δ ← a|
|y → Δ|
|(y) → Δ ← b|
|z → Δ ← c|
Now, as b changes values during the execution of the subroutine, y is unaffected, so that at the conclusion of the subroutine y has its original value.
The above analysis applies to function subprograms as well as to subroutines. Changes in the function variables during execution of a function subprogram induce corresponding changes in the variables used to call the function subprogram.