Category Archives: Undergrad posts

Fortran: More

Topics


Following is further Fortran information not covered in the lessons.

More Intrinsic Functions

This table lists additional functions intrinsic to Fortran, not already listed in Lesson 1.

Function Description
aint(x) truncates the decimal part of x
(without changing the type of x)
anint(x) rounds x to the nearest integer
(without changing the type of x)
int(x) converts x to integer type, giving it
the value of the integer closest to x
but no larger than x in absolute value
log10(x) common logarithm of x (base 10)
max(x1,x2,...,xn) maximum of x1, x2, ..., xn
min(x1,x2,...,xn) minimum of x1, x2, ..., xn
nint(x) converts x to integer type,
rounding x to the nearest integer

Save

This command, used in a subprogram, preserves the values of local variables (i.e., variables used in the subprogram but not listed in the title statement) from one call of the subprogram to the next. For instance, the statement

save m, z

in a subroutine ensures that in calls after the first run the subroutine remembers the final values of m and z from the previous run. A save statement by itself,
save    ,

preserves the values of all local variables in the subprogram. You cannot save a listed variable of the subprogram - the compiler will give an error message. (EG: If a subroutine's first line is "subroutine area(r)", then you cannot save r.)

Common (Blank)

Ordinarily the only information shared between the main program and subprograms are the values of variables appearing in variable lists. The common statement can be used to share additional information.
The simplest form of the common statement is the blank common statement. Let us suppose for illustration that the main program has real variables x and y as well as an integer variable n which are to be shared with one or more subroutines. Then at the beginning of the main program, before any executable statements, you first declare the types of x, y, and n and next insert the "blank common" statement
common x, y, n    .

This instructs Fortran to preserve three "common" memory locations for x, y, and n, designated as triangles below:
x → Δ
y → Δ
n → Δ

These memory locations are then accessible by all subroutines of the program containing a similar common statement (but with possibly different variables). For example, suppose a subroutine declares real variables u and v and an integer variable m. If the subroutine contains also the common statement
common u, v, m    ,

then u, v, and m will share memory locations with x, y, and n, respectively :
x → Δ ← u
y → Δ ← v
n → Δ ← m

When the values of u, v, and m change in the subroutine, then the values of x, y, and n in the main program change accordingly; and vice-versa - changes in x, y, or n in the main program produce changes in u, v, and m in the subroutine. Obviously, because of the sharing of memory locations, the types of x, y, and n must match those of u, v, and m, respectively (and also dimensions must match in the case of arrays.)
It is possible for a third or even more subroutines to share the same three memory locations. If a third subroutine has real variables a and b and an integer variable k, as well as the statement

common a, b, k    ,

then x, u, a share one memory location, y, v, b another, and n, m, k a third. A change in one of these variables in the main program or a subroutine produces the same change in whatever variables share the same memory location.
A common statement cannot list variables that are listed also in the title statement of the subprogram in which the common statement appears. (EG: If a subroutine's first line is "subroutine area(r)", then you cannot list r in the subroutine's common statement.)

Common (Named)

In programs with more than one subroutine it is sometimes desirable to share different sets of variables among different sets of program units. In such situations the named common statement is useful. The general form of this statement is

common / name1 / list1 / name2 / list2 / name3 / list3 / … / nameN / listN    .

The "names" are names for the different sets of variables, and the "lists" contain the names of variables in these sets.
Suppose, for example, that the main program uses variables A, B, C, D, E, F, G, while subroutine "demo1" uses variables A, B, C, D, and subroutine "demo2" uses variables C, D, E, F, G. If we want all program units using the same variable to share the value of that variable, then in the main program we insert the named common statement
common / first / A, B / second / C, D / third / E, F G     ,

in subroutine "demo 1" we insert
common / first / A, B / second / C, D    ,

and in "demo 2" we insert
common / second / C, D / third / E, F, G    .

Then the variable set "first" consists of A and B, and is shared by the main program and demo1. Variable set "second" consists of C and D and is shared by all three units. Variable set "third" consists of E, F, and G and is shared by the main program and "demo2". It is not necessary that different units use the same variable names for shared data. For example, subroutine "demo2" could name its five variables V, W, X, Y, Z; then its common statement would change to
common / second / V, W / third / X, Y, Z     ,

and consequently V and C would share a memory location, as would W and D, X and E, Y and F, and Z and G.

Data

A data statement is used to initialize (i.e., assign initial values to) variables before the program begins. All data statements must appear after parameter and type declarations; it is common practice to include them immediately following these statements.
The general form of a data statement is
data list1 / data1 / list2 / data2 / list3 / data 3 / ... / listN / dataN /     .

Each list is a list of variables separated by commas, and each data is a list of values of the variables in the preceding list. Following is a table of examples with the corresponding resulting assignments:
data x, y, z / 2.1, 3.3, -4.4 / x = 2.1, y = 3.3, z = - 4.4
data k, m, n, p / 3 * 0, 1 / k = m = n = 0, p = 1
data first, last / "Jane", "Smith" / first = "Jane", last = "Smith"
data A / 5.2 / B, C / 2.8, 3.9 / A = 5.2, B = 2.8, C = 3.9
data x, y / 2*1. / m,n / 2*0 / pi / 3.14 / x = y = 1., m = n = 0, pi = 3.14

Note that in a data list the notation "n * x" means that the value x is to be assigned to n successive variables in the preceding variable list.
Data statements were necessary in earlier versions of Fortran, when the compiler did not automatically initialize variables; in more modern versions of Fortran they can usually be omitted without repercussions.

Arithmetic If

The arithmetic if statement has the form

if (expression) k, m, n     ,

where expression is some numeric expression that Fortran can evaluate, and k, m, n are integers representing labels of executable statements. If expression is negative, zero, or positive, then the program jumps to the statement labeled k, m, or n, respectively. As illustration, a program solving a quadratic equation
ax2 + bx + c = 0

might have the arithmetic if statement
if (b * b - 4 * a * c) 10, 20, 30    .

Then if the discriminant b2 - 4ac is negative, the program jumps to the statement labeled 10, if it is zero the jump is to label 20, and if positive to label 30.

Computed Go To

The computed go to statement has the form
go to (n1 , n2 , ..., nm) integer expression    ,

where n1, n2, ..., nm are integers representing labels of executable statements, and integer expression is some integer - valued expression that Fortran can evaluate. If the value of this expression is 1, the program jumps to the statement labeled n1, if the value is 2 the program jumps to the statement labeled n2, etc. For example, suppose a program contains the sequence
print *, "Enter the number of the task you want to perform:"
read *, n
go to (10,12,14,16,18,20) n

If the user enters 1, the program jumps to the statement labeled 10, if the user enters 2 it jumps to statement 12, if the user enters 3 it jumps to 14, etc. If the user errs and enters an integer different from 1, 2, 3, 4, 5, 6, Fortran defaults to the first statement listed, in this case statement 10.

Fortran: Lesson 7

Lesson topics


View Demos
#1 #2 #3
Download Demos
#1 #2 #3

Sometimes it is convenient in a Fortran program to use files for accessing or storing data - especially when large amounts of data are involved. Too much keyboard input during the run of a program leads to mistakes and tedium, while too much screen output has similar consequences. Putting data into files - both for input and output - is a more leisurely and less error-prone approach.

Open

The open command is used to open files - that is, it makes files available so that Fortran can read or write to them. The simplest form of the command is
open (unit = number, file = "name")    .

In place of number you insert a positive integer (but not 6) to be used to refer to the file, and instead of name you insert the name of the file. Here are examples of open commands:
									open (unit = 2, file = "scores")
									open (unit = 7, file = "a:scores.txt")
									open (unit = 5, file = "h:\\results\\primes")
									open (unit = 24, file = "c:\\fortran\\data\\divisors.dat")

Fortran uses the unit number to access the file with later read and write statements. Several files can be open at once, but each must have a different number. There is one thing to remember about numbering a file - you cannot use the number 6, as GNU Fortran reserves that number to refer to the screen.
Note that quotes enclose the filename. Also, in specifying a directory path for a file, you must use double backslashes instead of single ones. Do not put a space on either side of the colon after the drive letter. If you do not specify a drive or directory path for a file, or if you specify the same drive upon which GNU Fortran is installed but without a path, GNU Fortran will by default assume the file is located on the same drive and in the same directory from where Fortran is running.
If the named file does not already exist, Fortran will create it; if it does exist, Fortran will replace it. (So don't mistakenly give the file the same name as another important file!)

Close

The close command is used to close one or more files - examples are
									close (5)
									close (1, 3, 8)
The first of these commands closes the file numbered 5, while the second closes the three files numbered 1, 3, and 8. It is not necessary to close files; all files will automatically be closed when an end or stop statement is executed. However, in programs handling large amounts of data it can be prudent to close files before the end of the program in order to avoid possible memory problems and to increase efficiency.

Write (to Files)

The write command is used to write data to a file. For example, the command
									write (7,*)
works like a print * command, except that data is written to the file numbered 7 instead of to the screen. The two statements
									print *, "The solutions to the equation are : ", x1, x2
									write (7,*) "The solutions to the equation are : ", x1, x2

produce exactly the same output, except that the first writes to the screen and the second to file number 7. The command "write (7,*)" on a line by itself serves as a line feed, skipping a line in the file numbered 7 before the next writing to that file.
You can also use write statements in conjunction with format statements to write to a file; this gives you better control of formatting. In the following, the first number in "write (7,5)" refers to the file number and the second to the label of the format statement:
									 	write (7,5) "The solutions are ", x1, " and ", x2
									5	format (a,f16.10,a,f16.10)

The "write (7,5)" command works exactly like the similar command "write (*,5)", except that in the former output is directed to file number 7, and in the latter to the screen.
Each execution of a write command writes to a single line in a file. The next write command will write to a new line.
Here is a program that finds and prints to a file the divisors of an integer n :
									program divisors
								c	This program finds the divisors of an integer input by the user.
								c	The divisors are printed to a file.
									integer n, k, d(10)
									open (unit = 1, file = "divisors")
									print *, "Enter a positive integer :"
									read *, n
									write (1,*) "Here are the divisors of ", n, " :"
									k = 0
									do i = 1, n
										if (mod(n,i) .eq. 0) then
											k = k + 1
											d(k) = i
										end if
										if (k .eq. 10) then
											write (1,5) (d(j), j = 1, 10)
											k = 0
										end if
									end do
									write (1,5) (d(j), j = 1, k)
								5	format (10i7)
									close (1)
									print *, "The divisors are listed in the file 'divisors'. Bye."
									end

Note that the program counts the divisors, storing them in an array d, until 10 are accumulated; then it prints these 10 on a single line, reserving 7 places for each divisor. It then begins a new count and repeats the procedure until all divisors are found. The last write statement prints whatever divisors are left over after the last full line of 10. The close statement, included here for demonstration only, is unnecessary, as the program is all but finished at that point and the end statement will automatically close the file anyway.

Read (from Files)

The read statement is used to read data from a file. Generally data is read from a file in the standard way, line-by-line and from left to right. But you must remember that each read statement begins reading a new line, whether or not the preceding read statement used all the data in the preceding line.
Suppose for example that a file is numbered 7, and that the first two lines of the file contain the data (separated by commas)
1.23 , 4.56 , 7.89
11, 13 , "Sally"

If the first two read statements in the program are
									read (7,*) x, y, z
									read (7,*) m, n, first
then the program assigns x = 1.23, y = 4.56, z = 7.89, m = 11, n = 13, first = "Sally". The variables will have to be declared in the program to correspond with the data assigned them by the read statements. For instance, in the above situation x, y, and z will have been declared real variables, m and n integers, and "first" a character variable. Failure to match variable types with data types will most likely lead to error messages.
It is possible that a program does not know beforehand the length of a file. If data is being read from a loop, there is a way to exit the loop when all data in the file has been read, thereby avoiding a program hang-up. One simply modifies the read statement to something like
									read (7,*,end=10)
This command instructs Fortran to read the next line in the file numbered 7, but to jump to the statement labelled 10 in the program in the event that the last line in that file has already been read.
You can also use format specifiers in read statements, but this can be somewhat tedious and we will not go into the details. As but one example, suppose you want to make the assignments
n = 77     ,     x = 123.45     ,     y = 67.8   ,

where n is an integer and x and y are real variables. Then you may use the read and format statements
										read (7,5) n, x, y
									5	format (i2,f5.2,f3.1)

and in file number 7 place the corresponding line of data
7712345678    .

Fortran will read and separate the data, insert appropriate decimal points, and assign it to the variables. But as you can see the method is confusing and perhaps not worth the effort.

Fortran: Lesson 6

Lesson topics


View Demos
# 1 # 2 # 3 # 4
Download Demos
# 1 # 2 # 3 # 4

Initializing Variables

Recall that in Basic the default value of a numeric variable is always zero - that is, if you introduce a numeric variable but do not specify its value, Basic automatically gives it the value zero. In GNU Fortran the situation is more confused. A real variable with no value specified will be given a value - but usually a very small value that is not precisely zero, and sometimes a value that is not even close to zero. An integer is given the default value 1. This strange behavior is hardly ever a problem, as usually when the variable is eventually used in the program it is given an appropriate value by some assignment statement. But trouble might arise if a forgetful programmer proceeds on the assumption that the default value is zero, or perhaps neglects to include an assignment statement. If you are worried about the problem, you can assign values to all your variables at the beginning of your program - a procedure called "initializing variables". The easiest way to do this is with ordinary assignment statements, such as "x = 0", or "y = 2.61", etc. (For programs with a large number of variables a more efficient method is to use DATA statements; we will discuss these later.)

Mod

In Fortran the expression mod(n,m) gives the remainder when n is divided by m; it is meant to be applied mainly to integers. Examples are
mod(8,3) = 2   ,   mod(27,4) = 3   ,   mod(11,2) = 1   ,   mod(20,5) = 0  .

Subroutines

A subroutine in Fortran works like a subprogram in Basic, except that you do not declare a subroutine. Subroutines are typed in the source file after the main program. A subroutine must have a name, followed by a list of variables in parentheses. A variable may be of any type, including a character variable, and can be an array. A subroutine begins with variable declaration statements, just as the main program.
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.
								end
When 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."
									end
The call statement for this subroutine,
									call bluesky
likewise 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
matmult

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)
									end
A call statement for this subroutine might be something like
									call prod(B,u,v)

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.

Return (in Subroutines)

A return statement in a subroutine instructs Fortran to terminate the subroutine and return to the main program at the point where it departed. Thus it works like a stop statement in the main program, halting the program prematurely before the final end statement. A subroutine may have several returns, but only one end statement.
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"
									end
The 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.

Variable Substitution in Subprograms

We look in more detail at how variables are substituted for one another in the calling and execution of a subroutine or function subprogram. Let us suppose for example that a certain subroutine named "demo" depends on three variables, say a, b, and c, so that the first line of the subroutine is
									subroutine demo(a,b,c)

Let us assume also that the main program's call statement for this subroutine is

									call demo(x,y,z)

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.

Fortran: Lesson 5

Lesson topics


View Demos
# 1 # 2 # 3
Download Demos
# 1 # 2 # 3

Arrays

There are only a few minor differences in the way Fortran and Basic treat arrays. Array declarations in Fortran go at the beginning of the program, before any executable statement. Arrays can be declared with either a dimension statement or a type declaration. The latter way is preferred, because it is best anyway to declare the type of the array. Here are examples of arrays introduced by type declarations:
real a(10), b(5) one-dimensional arrays a and b of
real variables, indexed from 1 to 10
and from 1 to 5, respectively
integer n(3:8), m one-dimensional array n of integers,
indexed from 3 to 8, and an integer
variable m
double precision c(4,5) two-dimensional array c of double
precision real numbers, the first
index running from 1 to 4, and the
second from 1 to 5
character student(30)*20 one-dimensional array student of
strings, indexed from 1 to 30, each
string up to 20 symbols long
real num(0:5,1:10,-3:3) three-dimensional array num of single
precision real numbers, the first index
running from 0 to 5, the second from
1 to 10, and the third from -3 to 3

In Fortran the default lower limit of the range of a subscript is 1, rather than 0 as in Basic. A colon separates the lower and upper limits whenever both are specified.
Because arrays are declared at the beginning of the program, they must be given a fixed size - i.e., the limits must be constants rather than variables. (In this respect Fortran is less flexible than Basic, in that Basic allows the dimension of an array to be a variable whose value can be input by the user, thereby ensuring that exactly the right amount of storage space is reserved.) You don't have to use the full size of the array specified in the declaration statements; that is, you may reserve space for more entries in the array than you will need.
If you use a dimension statement to declare an array, you should precede it with a type declaration. Here is one way to introduce a real array weights, indexed from 1 to 7:
real weights
dimension weights(7)

But the same can be accomplished more briefly with the single statement
real weights(7)   .

Although the upper and lower limits of an array cannot be variables, they can be constants declared in parameter statements. The sequence of statements
integer max
parameter (max = 100)
character names(max)*30
real scores(max)

instructs Fortran to set aside storage space for a list of at most 100 names, each a string of length no longer than 30 symbols, as well as a list of at most 100 scores, each a real number.
As in Basic, in Fortran you may input and print arrays with do loops. But you can sometimes more efficiently do the same with single statements. For instance, the above array weights can be input with only the statement
read *, weights   .

This read statement pauses the program to allow the user to enter all seven entries of the array. The user can either enter the seven weights one-by-one separated by returns, or alternatively, can enter all seven weights separated only by commas, and then a single return. If you want to input say only the first five weights, you can do so with the statement
read *, (weights(i), i=1,5)   .

Analogously, the single print statement
print *, weights

prints the seven entries of weights to the screen, while the statement
print *, (weights(i), i=p,q)

prints only the weights indexed from p to q.
There are various formatting tricks useful in printing two-dimensional arrays. Here is one example demonstrating how to print a matrix A having 5 rows and 6 columns of real numbers, with each row of the matrix printed on its own line :
do i = 1, 5
write (*,10) (A(i,j), j = 1, 6)
end do
10 format (6f7.3)

More precise formatting can be accomplished with double loops and tab indicators.

Function Subprograms

Function subprograms in Fortran define functions too complicated to describe in one line. Here is a function subprogram defining the factorial function, fact(n) = n! :
function fact(n)
integer fact, n, p
p = 1
do i = 1, n
p = p * i
end do
fact = p
end

The first line of the function subprogram specifies the name of the function, and lists in parentheses the variables upon which the function depends. The subprogram has its own type statements, declaring the type of the function itself, as well as the types of the variables involved in computing the function. Somewhere in the subprogram there must be a line giving the value of the function. (Above it is the line "fact = p".) The subprogram concludes with an end statement. In Fortran, function subprograms do not have to be declared as they do in Basic. The entire function subprogram appears in the source file after the final end statement of the main program.
The above factorial subprogram, with variables of integer type, works only for nonnegative integers no larger than 12, as 13! = 6,227,020,800 exceeds the Fortran upper limit of 2,147,483,647 for integers. To handle larger integers, the types can be changed to real or double precision. In GNU Fortran, single precision real type handles factorials of integers as large as 34, and double precision as large as 170.
The main program (or in fact any subprogram) utilizing a function subprogram should likewise specify the type of the function. Here is a simple main program using the above factorial function "fact":
program demofactorial
integer fact, n
print *, "What is n?"
read *, n
print *, "The value of", n, " factorial is", fact(n)
end

Because n is declared an integer in the function subprogram defining fact(n), it must also be an integer in the main program when fact(n) is evaluated; if it is of a different type the compiler displays a type mismatch error message.
A function subprogram may depend on several variables, and it may use an already defined statement function or a function defined by another function subprogram. Following is a function subprogram utilizing the above factorial function subprogram; it computes the Poisson probability function, defined as
P(n,t) = tn e- t / n!   ,

where n is a nonnegative integer and t any positive number:
function poisson(n,t)
real poisson, t
integer n, fact
poisson = (t ** n) * exp(-t) / fact(n)
end

Note that, as this subprogram references the function "fact", it must declare its type. Both this subprogram and the factorial subprogram will appear in the source file following the end statement for the main program. (The order in which the subprograms are typed makes no difference - just as long as they both follow the main program.)
Again, in referencing function subprograms one must respect types; for example, if the main program is to compute poisson(m,s) for some variables m and s, then, in order to conform to the type declarations in the function poisson, m must first be declared an integer and s of real type. Oversights will lead to compiler type-mismatch messages.

Arrays in Function Subprograms

An array can be listed as a variable of a function defined by a function subprogram - but you just write the array name, with no parentheses after the name as in Basic. The type and dimension of the array must be specified in the function subprogram.
Following is a program called "mean" that computes the mean, or average, of a list containing up to 100 numbers. The main program prompts for the list of numbers, and then references a function subprogram named "avg" that computes the average.
program mean
real numbers(100), avg
integer m
print *, "How many numbers are on your list?"
print *, "(no more than 100, please)"
read *, m
do i =1, m
print *, "Enter your next number:"
read *, numbers(i)
end do
print *, "The average is", avg(m,numbers)
end
 
function avg(n,list)
real avg, list(100), sum
integer n
sum = 0
do i = 1, n
sum = sum + list(i)
end do
avg = sum/n
end

Note that both the main program and the subprogram declare the type of the function "avg". The main program calls the function subprogram with the arguments "m" and "numbers", and these are substituted into the function subprogram for the variables "n" and "list". The main program specifies the dimension of the array "numbers", while the subprogram specifies the dimension of the array "list". The subprogram does its calculations and returns the value of "avg" to the main program. For this procedure to work, the types of the variables "m" and "n" must agree, as well as the types of "numbers" and "list".

Return (in Function Subprograms)

A return statement in a function subprogram acts like a stop statement in the main program; the subprogram is terminated and Fortran returns to where it left off in the main program. Here is a function subprogram defined on integers n; the value of the function "demo" is 0 if n ≤ 0, and if n > 0 it is the sum of the squares of the integers from 1 to n:
function demo(n)
integer demo, n
demo = 0
if (n .le. 0) return
do i =1, n
demo = demo + i * i
end do
end