• Tidak ada hasil yang ditemukan

Fortran 90 Tutorial_4.doc (437Kb)

N/A
N/A
Protected

Academic year: 2018

Membagikan "Fortran 90 Tutorial_4.doc (437Kb)"

Copied!
54
0
0

Teks penuh

(1)

F

UNCTIONS

AND

M

ODULES

S

ELECT THE TOPICS YOU WISH TO REVIEW

:

Functions and Modules

Designing Functions

Functions Examples

Common Problems

Using Functions

Argument Association

Where Do My Functions Go?

Scope Rules Programming Examples:

Computing Cubes

Computing Means - Revisited

Cm and Inch Conversion

Heron'a Formula for Computing Triangle Area - Revisited

Computing the Combinatorial Coefcient

Computing Square Roots with Newton's Method

Designing a Greatest Common Divisor Function

Finding All Prime Numbers in the Range of 2 and N - Revisited

The Bisection (Bozano) Equation Solver

A Brief Introduction to Modules

What is a Module?

How to Use a Module?

Compile Programs with Modules

Programming Example 1: Factorial and Combinatorial Coefcient

Programming Example 2: Trigonometric Functions Using Degree

(2)

External Functions and Interface Blocks

Interface Blocks

Programming Example 1: Cm and Inch Conversion

Programming Example 2: Heron'a Formula for Computing Triangle Area

Download my course overheads

D

ESIGNING

F

UNCTIONS

S

YNTAX

In addition to intrinsic functions, Fortran allows you to design your own functions. A Fortran function, or more precisely, a Fortran function subprogram, has the following syntax:

type FUNCTION function-name (arg1, arg2, ..., argn) IMPLICIT NONE

[specification part] [execution part] [subprogram part]

END FUNCTION function-name

Here are some elaborations of the above syntax:

 The first line of a function starts with the keyword FUNCTION. Before FUNCTION,

the type gives the type of the function value (i.e., INTEGER, REAL, LOGICAL and CHARACTER) and after FUNCTION is the name you assign to that function.

 Following the function-name, there is a pair of parenthesis in which a number of

arguments arg1, arg2, ..., argn are separated with commas. These arguments are referred to as formal arguments. Formal arguments must be variable names and cannot be expressions. Here are a examples:

1. The following is a function called Factorial. It takes only one formal argument n and returns an INTEGER as its function value.

 INTEGER FUNCTION Factorial(n)

1. The following is a function called TestSomething. It takes three formal arguments a, b and c, and returns a LOGICAL value (i.e., .TRUE. or .FALSE.) as its function value.

 LOGICAL FUNCTION TestSomething(a, b, c)

 A function must be ended with END FUNCTION followed by the name of that

function.

 Between FUNCTION and END FUNCTION, there are the IMPLICIT NONE,

specification part, execution part and subprogram part. These are exactly identical to that of a PROGRAM.

If a function does not need any formal argument, it can be written as

(3)

[specification part] [execution part] [subprogram part]

END FUNCTION function-name

where arg1, arg2, ..., argn are left out. But, the pait of parenthesis must be there.

S

EMANTICS

The meaning of a function is very simple:

 A function is a self-contained unit that receives some "input" from the outside world

via its formal arguments, does some computations, and then returns the result with the name of the function.

 Thus, since the function returns its result via the name of the function, somewhere in

the function there must exist one or more assignment statements like the following:

 function-name = expression

where the result of expression is stored to the name of the function.

However, the name of the function cannot appear in the right-hand side of any

expression. That is, the name of the function, used as a variable name, can only appear in

the left-hand side of an expression. This is an artificial restriction in this course only.

 A function receives its input values from formal arguments, does computations, and

saves the result in its name. When the control of execution reaches END FUNCTION, the value stored in the name of the function is returned as the function value.

 To tell the function about the types of its formal arguments, all arguments must be

declared with a new attribute INTENT(IN). The meaning of INTENT(IN) indicates that the function will only take the value from the formal argument and must not

change its content.

 Any statements that can be used in PROGRAM can also be used in a FUNCTION.

FUNCTIONS EXAMPLES

Here are a few examples of functions:

 The following function has a name Sum and three formal arguments a, b and c. It

returns an INTEGER function value. The INTEGER, INTENT(IN) part indicates that the function takes its input value from its three formal argument. Then, the function uses the value of these formal arguments to compute the sum and stores in Sum, the name of the function. Since the next statement is END FUNCTION, the function returns the value stored in Sum.

(4)

INTEGER, INTENT(IN) :: a, b, c Sum = a + b + c

END FUNCTION Sum

If the value supplied to a, b and c are 3, 5, and -2, respectively, Sum will receive 6 (=3+5+(-2)) and the function returns 6.

 The following function has a name Positive with a REAL formal argument. If the

argument is positive, the function returns .TRUE.; otherwise, the function returns .FALSE.

LOGICAL FUNCTION Positive(a) IMPLICIT NONE

REAL, INTENT(IN) :: a IF (a > 0.0) THEN Positive = .TRUE. ELSE

Positive = .FALSE. END IF

END FUNCTION Positive

The above function can be made much shorter by using LOGICAL assignment. In the following, if a > 0.0 is true, .TRUE. is stored to Positive; otherwise, Positive receives .FALSE.

LOGICAL FUNCTION Positive(a) IMPLICIT NONE

REAL, INTENT(IN) :: a Positive = a > 0.0 END FUNCTION Positive

 The following function, LargerRoot, takes three REAL formal arguments and returns

a REAL function value. It returns the larger root of a quadratic equation ax2 + bx + c

= 0.

REAL FUNCTION LargerRoot(a, b, c) IMPLICIT NONE

REAL, INTENT(IN) :: a REAL, INTENT(IN) :: b REAL, INTENT(IN) :: c

(5)

LargerRoot = r2 END IF

END FUNCTION LargerRoot

The above example shows that you can declare other variables such as d, r1 and r2 if they are needed.

 The following function, Factorial(), has only one INTEGER formal argument n >= 0,

and computes and returns the factorial of n, n!.

INTEGER FUNCTION Factorial(n) IMPLICIT NONE

INTEGER, INTENT(IN) :: n INTEGER :: i, Ans Ans = 1

DO i = 1, n Ans = Ans * i END DO

Factorial = Ans END FUNCTION

Note that the function name Factorial is not used in any computation. Instead, a new INTEGER variable is used for computing n!. The final value of Ans is stored to Factorial before leaving the function.

If Factorial is involved in computation like the following:

INTEGER FUNCTION Factorial(n) IMPLICIT NONE

INTEGER, INTENT(IN) :: n INTEGER :: i Factorial = 1

DO i = 1, n

Factorial = Factorial * i END DO

END FUNCTION

then there is a mistake although the above program looks normal. The reason is that the function name cannot appear in the right-hand side in any expression of that function.

 The following function GetNumber() does not have any formal arguments and

returns an INTEGER function value. This function has a DO-loop which keeps asking the user to input a positive number. The input is read into the function name. If this value is positive, then EXIT and the function returns the value in GetNumber. Otherwise, the loop goes back and asks the user again for a new input value.

(6)

DO

WRITE(*,*) 'A positive real number --> ' READ(*,*) GetNumber

IF (GetNumber > 0.0) EXIT

WRITE(*,*) 'ERROR. Please try again.' END DO

WRITE(*,*)

END FUNCTION GetNumber

C

OMMON

P

ROBLEMS

Forget the type of a FUNCTION.

FUNCTION DoSomething(a, b) IMPLICIT NONE

INTEGER, INTENT(IN) :: a, b DoSomthing = SQRT(a*a + b*b) END FUNCTION DoSomthing

If there is no type, you will not be able to determine if the returned value is an INTEGER, a REAL or something else.

Forget INTENT(IN).

REAL FUNCTION DoSomething(a, b) IMPLICIT NONE

INTEGER :: a, b

DoSomthing = SQRT(a*a + b*b) END FUNCTION DoSomthing

Actually, this is not an error. But, without INTENT(IN), our Fortran compiler will not be able to check many potential errors for you.

Change the value of a formal argument declared with INTENT(IN).

REAL FUNCTION DoSomething(a, b) IMPLICIT NONE

INTEGER, INTENT(IN) :: a, b IF (a > b) THEN

a = a - b ELSE

(7)

DoSomthing = SQRT(a*a + b*b) END FUNCTION DoSomthing

Since formal argument a is declared with INTENT(IN), its value cannot be changed.

Forget to store a value to the function name.

REAL FUNCTION DoSomething(a, b) IMPLICIT NONE

INTEGER, INTENT(IN) :: a, b INTEGER :: c c = SQRT(a*a + b*b) END FUNCTION DoSomthing

When the execution of this function reaches END FUNCTION, it returns the value stored in DoSomething. However, in the above, since there is no value ever stored in DoSmething, the returned value could be anything (i.e., a garbage value).

Function name is used in the right-hand side of an expression.

REAL FUNCTION DoSomething(a, b) IMPLICIT NONE

INTEGER, INTENT(IN) :: a, b DoSomething = a*a + b*b

DoSomething = SQRT(DoSomething) END FUNCTION DoSomthing

In the above, function name DoSomething appears in the right-hand side of the second expression. This is a mistake. Only a special type of functions, RECURSIVE functions, could have their names in the right-hand side of expressions.

Only the most recent value stored in the function name will be returned..

REAL FUNCTION DoSomething(a, b) IMPLICIT NONE

INTEGER, INTENT(IN) :: a, b DoSomething = a*a + b*b

DoSomething = SQRT(a*a - b*b) END FUNCTION DoSomthing

In the above, the value of SQRT(a*a-b*b) rather than the value of a*a + b*b is returned. In fact, this is obvious. Since the name of a function can be considered as a special variable name, the second assignment overwrites the previous value.

(8)

The way of using a user-defined function is exactly identical to that of using Fortran intrinsic

functions. One can use a function in an expression and in a WRITE. Suppose we have the

following function:

REAL FUNCTION Average(x, y, z) IMPLICIT NONE

REAL, INTENT(IN) :: x, y, z Average = (x + y + z) / 3.0 END FUNCTION Average

This function takes three REAL formal arguments and returns their average.

To use this function, one needs to supply values to the formal arguments. For example, one could

write the following:

... = ... + Average(1.0, 2.0, 3.0) * ...

The above expression involves the use of function Average. Since this function has three formal arguments, three values must be presented to the function. Here, the values are 1.0, 2.0 and 3.0 and the returned value is the average of these three numbers (i.e., 2.0). The values or expressions used to invoke a function are referred to as actual arguments.

Please keep the following important rules in mind:

The number of formal arguments and actual arguments must be equal.

... = ... + Average(1.0, 2.0, 3.0, 4.0) * .... ... = ... - Average(3.0, 6.0) + ...

The first line has more actual arguments than the number of formal arguments, and the second line has less actual arguments than the number of formal arguments.

The type of the corresponding actual and formal arguments must be identical.

WRITE(*,*) Average(1, 2.5, 3.7)

In the above example, the first actual argument is an INTEGER which doe not match with the type of the first formal argument. Thus, it is incorrect.

The actual arguments can be constants, variables and even expressions.

REAL :: a = 1.0, b = 2.0, c = 3.0

... = ... + Average(1.0, 2.0, 3.0) + ... ... = ... + Average(a, b, c) + ...

(9)

In the above, the first line shows the use of constants as actual arguments. The second line uses variables, while the third uses expression. In the third line, the result of evaluating a+b, b*c and (b+c)/a will be supplied to the three formal arguments of function Average().

Please continue with the next page on argument association

A

RGUMENT

A

SSOCIATION

When using a function, the values of actual arguments are passed to their corresponding formal

arguments. There are some important rules:

 If an actual argument is an expression, it is evaluated and the result is saved into a

temporary location. Then, the value in this temporary location is passed.

 If an actual argument is a constant, it is considered as an expression. Therefore, its

value is saved to a temporary location and then passed.

 If an actual argument is a variable, its value is taken and passed to the

corresponding formal argument.

 If an actual argument is a variable enclosed in a pair of parenthesis like (A), then this

is an expression and its value is evaluated and saved to a temporary location. Then, this value (in the temporary location) is passed.

 For a formal argument declared with INTENT(IN), any attempt to change its value in

the function will cause a compiler error. The meaning of INTENT(IN) is that this formal argument only receives a value from its corresponding actual argument and its value cannot be changed.

 Based on the previous point, if a formal argument is declared without using

INTENT(IN), its value can be changed. For writing functions, this is not a good practice and consequently all formal arguments should be declared with INTENT(IN).

E

XAMPLE

We shall use the following function to illustrate the above rules. Function Small() takes three formal arguments x, y and z and returns the value of the smallest.

INTEGER :: a, b, c INTEGER FUNCTION Small(x, y, z) IMPLICIT NONE

a = 10 INTEGER, INTENT(IN) :: x, y, z b = 5

c = 13 IF (x <= y .AND. x <= z) THEN WRITE(*,*) Small(a,b,c) Small = x

WRITE(*,*) Small(a+b,b+c,c) ELSE IF (y <= x .AND. y <= z) THEN WRITE(*,*) Small(1, 5, 3) Small = y

WRITE(*,*) Small((a),(b),(c)) ELSE

(10)

END IF

END FUNCTION Small

In the first WRITE, all three arguments are variable and their values are sent to the

corresponding formal argument. Therefore, x, y and z in function Small() receives 10, 5 and 13,

respectively. The following diagram illustrate this association:

In the second WRITE, the first and second arguments are expression a+b, b+c. Thus, they are

evaluated yielding 15 and 18. These two values are saved in two temporary locations and passed

to function Small() along with variable c. Thus, x, y and z receive 15, 18 and 13 respectively.

This is illustrated as follows. In the figure, squares drawn with dotted lines are temperary

locations that are created for passing the values of arguments.

In the third WRITE, since all actual arguments are constants, their values are "evaluated" to

temporary locations and then sent to x, y and z.

(11)

Thus, x, y and z receive 10, 5 and 13, respectively.

Note that while the formal arguments of function Small() receive the same values using the

first and the fourth lines, the argument associations are totally different. The first line has

the values in variables passed directly and the the fourth line evaluates the expressions into

temporary locations whose values are passed. This way of argument association does not

have impact on functions (since you must use INTENT(IN)), it will play an important role

in subroutine subprograms.

W

HERE

D

O

M

Y

F

UNCTIONS

G

O

?

Now you have your functions. Where do they go? There are two places for you to add these

functions in. They are either internal or external. This page only describes internal functions.

See

external subprogram

for the details of using external functions.

Long time ago, we mentioned the

structure

of a Fortran program. From there, we know that the

last part of a program is

subprogram part

. This is the place for us to put the functions. Here is the

syntax:

PROGRAM program-name IMPLICIT NONE

[specification part] [execution part] CONTAINS

[your functions]

END PROGRAM program-name

In the above, following all executable statements, there is the keyword CONTAINS, followed by all of your functions, followed by END PROGRAM.

From now on, the program is usually referred to as the main program or the main program

unit. A program always starts its execution with the first statement of the main program. When a

function is required, the control of execution is transfered into the corresponding function until

the function completes its task and returns a function values. Then, the main program continues

its execution and uses the returned function value for further computation.

(12)

T

HE FOLLOWING COMPLETE PROGRAM

"

CONTAINS

"

ONE FUNCTION

, A

VERAGE

().

T

HE EXECUTION PART CONSISTS OF THREE STATEMENTS

,

A

READ,

AN ASSIGNMENT AND A

WRITE. T

HESE THREE STATEMENTS MUST BE PLACED

BEFORE THE KEYWORD

CONTAINS. N

OTE ALSO THAT

END PROGRAM

MUST BE THE LAST LINE OF YOUR PROGRAM

.

G

EO

M

EAN

(). T

HE ORDER OF THESE FUNCTIONS ARE UNIMPORTANT

.

PROGRAM TwoFunctions

GeometricMean = GeoMean(a,b) WRITE(*,*) 'Input = ', a, b

WRITE(*,*) 'Larger one = ', BiggerOne

WRITE(*,*) 'Geometric Mean = ', GeometricMean

(13)

A I

MPORTANT

N

OTE

Although in general a function can "contain"

other functions,

an internal function CANNOT contain any other functions.

In the following example, the main program "contains" an internal function InternalFunction(),

which in turn contains another internal function Funct(). This is incorrect, since an internal

function cannot contain another internal function. In other words, the internal functions of a main

program must be on the same level.

PROGRAM Wrong IMPLICIT NONE ... CONTAINS

INTEGER FUNCTION InternalFunction(...) IMPLICIT NONE

... CONTAINS

REAL FUNCTION Funct(...) IMPLICIT NONE

... END FUNCTION Funct

END FUNCTION InternalFunction END PROGRAM Wrong

Please continue with the next important topic about scope rules.

S

COPE

R

ULES

Since a main program could contain many functions and in fact a function can contain other

functions (

i.e.

, nested functions), one may ask the following questions:

1. Could a function use a variable declared in the main program? 2. Could a main program use a variable declared in one of its function?

The scope rules answer these questions. In fact, scope rules tell us if an entity (i.e., variable, parameter and function) is "visible" or accessible at certain places. Thus, places where an entity can be accessed or visible is referred to the scope of that entity.

The simplest rule is the following:

Scope Rule 1

The scope of an entity is the

(14)

in which it is declared.

Therefore, in the following, the scope of parameter PI and variables m and n is the main

program, the scope of formal argument k and REAL variables f and g is function Funct1(), and

the scope of formal arguments u and v is function Funct2().

PROGRAM Scope_1 IMPLICIT NONE

REAL, PARAMETER :: PI = 3.1415926 INTEGER :: m, n

... CONTAINS

INTEGER FUNCTION Funct1(k) IMPLICIT NONE

INTEGER, INTENT(IN) :: k REAL :: f, g ...

END FUNCTION Funct1

REAL FUNCTION Funct2(u, v) IMPLICIT NONE

REAL, INTENT(IN) :: u, v ...

END FUNCTION Funct2 END PROGRAM Scope_1

There is a direct consequence of Scope Rule 1. Since an entity declared in a function has a scope

of that function, this entity cannot be seen from outside of the function. In the above example,

formal argument k and variables f and g are declared within function Funct1(), they are only

"visible" in function Funct1() and are not visible outside of Funct1(). In other words, since k, f

and g are not "visible" from the main program and function Funct2(), they cannot be used in the

main program and function Funct2(). Similarly, the main program and function Funct1() cannot

use the formal arguments u and v and any entity declared in function Funct2().

L

OCAL

E

NTITIES

Due to the above discussion, the entities declared in a function or in the main program are said local to that function or the main program. Thus, k, f and g are local to function Funct1(), u and v are local to function Funct2(), and PI, m and n are local to the main program.

G

LOBAL

E

NTITIES

(15)

This comes the second scope rule:

Scope Rule 2

A global entity is visible to all contained functions,

including the function in which that entity is declared.

Continue with the above example, since m and n are global to both functions Funct1() and

Funct2(), they can be used in these two functions.

PROGRAM Scope_2 IMPLICIT NONE

INTEGER :: a = 1, b = 2, c = 3 WRITE(*,*) Add(a)

c = 4

WRITE(*,*) Add(a) WRITE(*,*) Mul(b,c) CONTAINS

INTEGER FUNCTION Add(q) IMPLICIT NONE

INTEGER, INTENT(IN) :: q Add = q + c

END FUNCTION Add

INTEGER FUNCTION Mul(x, y) IMPLICIT NONE

INTEGER, INTENT(IN) :: x, y Mul = x * y

END FUNCTION Mul END PROGRAM Scope_2

In the above program, variables a, b and c are global to both functions Add() and Mul(). Therefore, since variable c used in function Add() is global to Add(), expression q + c means computing the sum of the value of the formal argument q and the value of global variable c. Therefore, the first WRITE produces 4 (= 1 + 3). Before the second WRITE, the value of c is changed to 4 in the main program. Hence, the second WRITE produces 5 (= 1 + 4). The third WRITE produces 8 (= 2 * 4).

Thus, the first two WRITEs produce different results even though their actual arguments are the

same! This is usually refereed to as a side effect. Therefore, if it is possible, avoid using global

variables in internal functions.

Let us continue with the above example. To remove side effect, one could add one more

argument to function Add() for passing the value of c.

PROGRAM Scope_2 IMPLICIT NONE

(16)

WRITE(*,*) Add(a, c) c = 4

WRITE(*,*) Add(a, c) WRITE(*,*) Mul(b,c) CONTAINS

INTEGER FUNCTION Add(q, h) IMPLICIT NONE

INTEGER, INTENT(IN) :: q, h Add = q + h

END FUNCTION Add

INTEGER FUNCTION Mul(x, y) IMPLICIT NONE

INTEGER, INTENT(IN) :: x, y Mul = x * y

END FUNCTION Mul END PROGRAM Scope_2

W

HAT

I

F

T

HERE

A

RE

N

AME

C

ONFLICTS

?

Frequently we may have a local entity whose name is identical to the name of a global entity. To resolve this name confict, we need the following new scope rule:

Scope Rule 3

An entity declared in the scope of another

entity is always

a diferent entity even if their names are identical.

In the program below, the main program declares a variable i, which is global to function Sum().

However, i is also declared in function Sum(). According to Scope Rule 3 above, these two is are

two different entities. More precisely, when the value of Sum()'s i is changed, this change will

not affect the i in the main program and vice versa. This would save us a lot of time in finding

variables with different names.

PROGRAM Scope_3 IMPLICIT NONE

INTEGER :: i, Max = 5 DO i = 1, Max

Write(*,*) Sum(i) END DO

CONTAINS

INTEGER FUNCTION Sum(n) IMPLICIT NONE

INTEGER, INTENT(IN) :: n INTEGER :: i, s s = 0

(17)

s = s + i END DO

Sum = s

END FUNCTION Sum END PROGRAM Scope_3

Programming Examples:

C

OMPUTING

C

UBES

P

ROBLEM

S

TATEMENT

Write a program to compute the cubes of 1, 2, 3, ..., 10 in both INTEGER and REAL types. It is

required to write a function intCube() for computing the cube of an integer and a function

realCube() for computing the cube of a real.

S

OLUTION

! ---! This program display the cubes of INTEGERs and ! REALs. The cubes are computed with two functions: ! intCube() and realCube().

! ---PROGRAM Cubes

IMPLICIT NONE

INTEGER, PARAMETER :: Iterations = 10 INTEGER :: i

REAL :: x DO i = 1, Iterations x = i

WRITE(*,*) i, x, intCube(i), realCube(x) END DO

CONTAINS

! ---! INTEGER FUNCTION intCube() :

! This function returns the cube of the argument. ! INTEGER FUNCTION intCube(Number)

IMPLICIT NONE

(18)

END FUNCTION intCube

! ---! REAL FUNCTION realCube() :

! This function returns the cube of the argument. ! REAL FUNCTION realCube(Number)

IMPLICIT NONE

REAL, INTENT(IN) :: Number

realCube = Number*Number*Number END FUNCTION realCube

END PROGRAM Cubes

Click here to download this program.

P

ROGRAM

I

NPUT AND

O

UTPUT

The following is the output from the above program.

1, 1., 1, 1. 2, 2., 8, 8. 3, 3., 27, 27. 4, 4., 64, 64. 5, 5., 125, 125. 6, 6., 216, 216. 7, 7., 343, 343. 8, 8., 512, 512. 9, 9., 729, 729. 10, 10., 1000, 1000.

D

ISCUSSION

 Functions intCube() and realCube() are identical except for the types of formal

arguments and returned values.

 The main program has a DO-loop that iterates Iterations times (this is a

PARAMETER, or an alias, of 10). Variable x holds the real value of integer variable i.

C

OMPUTING

M

EANS

- R

EVISITED

P

ROBLEM

S

TATEMENT

(19)

Write a program to read three positive numbers and use three functions to compute the

arithmetic, geometric and harmonic means.

S

OLUTION

! ---! This program contains three functions for computing the ! arithmetic, geometric and harmonic means of three REALs. ! ---PROGRAM ComputingMeans

IMPLICIT NONE REAL :: a, b, c READ(*,*) a, b, c

WRITE(*,*) 'Input: ', a, b, c WRITE(*,*)

WRITE(*,*) 'Arithmetic mean = ', ArithMean(a, b, c) WRITE(*,*) 'Geometric mean = ', GeoMean(a, b, c) WRITE(*,*) 'Harmonic mean = ', HarmonMean(a, b, c) CONTAINS

! ---! REAL FUNCTION ArithMean() :

! This function computes the arithmetic mean of its ! three REAL arguments.

! REAL FUNCTION ArithMean(a, b, c)

IMPLICIT NONE

REAL, INTENT(IN) :: a, b, c ArithMean = (a + b + c) /3.0 END FUNCTION ArithMean

! ---! REAL FUNCTION GeoMean() :

! This function computes the geometric mean of its ! three REAL arguments.

! REAL FUNCTION GeoMean(a, b, c)

(20)

REAL, INTENT(IN) :: a, b, c GeoMean = (a * b * c)**(1.0/3.0) END FUNCTION GeoMean

! ---! REAL FUNCTION HarmonMean() :

! This function computes the harmonic mean of its ! three REAL arguments.

! REAL FUNCTION HarmonMean(a, b, c)

IMPLICIT NONE

REAL, INTENT(IN) :: a, b, c

HarmonMean = 3.0 / (1.0/a + 1.0/b + 1.0/c) END FUNCTION HarmonMean

END PROGRAM ComputingMeans

Click here to download this program.

P

ROGRAM

I

NPUT AND

O

UTPUT

The following is the output from the above program.

Input: 10., 15., 18. Arithmetic mean = 14.333333 Geometric mean = 13.9247675 Harmonic mean = 13.5

D

ISCUSSION

 Each of these functions is simple and does not require further explanation.

 Note that the main program and all three functions use the same names a, b and c.

By Scope Rule 3, they are all diferent entities. That is, when function ArithMean() is using a, it is using its own local formal argument rather than the global variable a declared in the main program.

C

M

AND

I

NCH

C

ONVERSION

P

ROBLEM

S

TATEMENT

It is known that 1 cm is equal to 0.3937 inch and 1 inch is equal to 2.54 cm. Write a program to

convert 0, 0.5, 1, 1.5, ..., 8, 8.5, 9, 9.5, and 10 from cm to inch and from inch to cm.

S

OLUTION

(21)

! (1) Cm_to_Inch() takes a real inch unit and converts ! it to cm unit, and

! (2) Inch_to_cm() takes a real cm unit and converts it ! to inch unit.

! The main program uses these functions to convert 0, 0.5, 1, 1.5, ! 2.0, 2.5, ..., 8.0, 8.5, 9.0, 9.5 and 10.0 inch (resp., cm) to ! cm (resp., inch).

! ---PROGRAM Conversion

IMPLICIT NONE

REAL, PARAMETER :: Initial = 0.0, Final = 10.0, Step = 0.5 REAL :: x

x = Initial

DO ! x = 0, 0.5, 1.0, ..., 9.0, 9.5, 10 IF (x > Final) EXIT

WRITE(*,*) x, 'cm = ', Cm_to_Inch(x), 'inch and ', & x, 'inch = ', Inch_to_Cm(x), 'cm'

x = x + Step END DO

CONTAINS

! ---! REAL FUNCTION Cm_to_Inch()

! This function converts its real input in cm to inch.

! REAL FUNCTION Cm_to_Inch(cm)

IMPLICIT NONE

REAL, INTENT(IN) :: cm

REAL, PARAMETER :: To_Inch = 0.3937 ! conversion factor Cm_to_Inch = To_Inch * cm

END FUNCTION Cm_to_Inch

! ---! REAL FUNCTION Inch_to_Cm()

! This function converts its real input in inch to cm.

! REAL FUNCTION Inch_to_Cm(inch)

IMPLICIT NONE

REAL, INTENT(IN) :: inch

REAL, PARAMETER :: To_Cm = 2.54 ! conversion factor Inch_to_Cm = To_Cm * inch

END FUNCTION Inch_to_Cm END PROGRAM Conversion

(22)

P

ROGRAM

I

NPUT AND

O

UTPUT

The following is the output from the above program.

0.E+0cm = 0.E+0inch and 0.E+0inch = 0.E+0cm

0.5cm = 0.196850002inch and 0.5inch = 1.26999998cm 1.cm = 0.393700004inch and 1.inch = 2.53999996cm 1.5cm = 0.590550005inch and 1.5inch = 3.80999994cm 2.cm = 0.787400007inch and 2.inch = 5.07999992cm 2.5cm = 0.984250009inch and 2.5inch = 6.3499999cm 3.cm = 1.18110001inch and 3.inch = 7.61999989cm 3.5cm = 1.37794995inch and 3.5inch = 8.88999939cm 4.cm = 1.57480001inch and 4.inch = 10.1599998cm 4.5cm = 1.77165008inch and 4.5inch = 11.4300003cm 5.cm = 1.96850002inch and 5.inch = 12.6999998cm 5.5cm = 2.16534996inch and 5.5inch = 13.9699993cm 6.cm = 2.36220002inch and 6.inch = 15.2399998cm 6.5cm = 2.55905008inch and 6.5inch = 16.5100002cm 7.cm = 2.75589991inch and 7.inch = 17.7799988cm 7.5cm = 2.95274997inch and 7.5inch = 19.0499992cm 8.cm = 3.14960003inch and 8.inch = 20.3199997cm 8.5cm = 3.34645009inch and 8.5inch = 21.5900002cm 9.cm = 3.54330015inch and 9.inch = 22.8600006cm 9.5cm = 3.74014997inch and 9.5inch = 24.1299992cm 10.cm = 3.93700004inch and 10.inch = 25.3999996cm

D

ISCUSSION

 Function Cm_to_Inch() converts its formal argument cm to inch, which is returned

as the function value. Please note that the constant 0.3937 is defined as a PARAMETER.

 Function Inch_to_Cm() converts its formal argument inch to cm, which is returned

as the function value. Please note that the constant 2.54 is defined as a PARAMETER.

 The main program uses DO-EXIT-END DO to generate 0, 0.5, 1, 1.5, ..., 8, 8.5, 9, 9.5

and 10. For each value, Cm_to_Inch() and Inch_to_Cm() are called to perform the desired conversion.

H

ERON

'

S

F

ORMULA

FOR

C

OMPUTING

T

RIANGLE

A

REA

- R

EVISITED

P

ROBLEM

S

TATEMENT

Given a triangle with side lengths a, b and c, its area can be computed using the Heron's formula:

(23)

In order for a, b and c to form a triangle, two conditions must be satisfied. First, all side lengths

must be positive:

Second, the sum of any two side lengths must be greater than the third side length:

Write a program to read in three real values and use a function for testing the conditions and

another function for computing the area. Should the conditions fail, your program must keep

asking the user to re-enter the input until the input form a triangle. Then, the other function is

used to compute the area.

S

OLUTION

! ---! This program uses Heron's formula to compute the area of a

! triangle. It "contains" the following functions; ! (1) LOGICAL function TriangleTest()

-! this function has three real formal arguments and tests ! to see if they can form a triangle. If they do form a ! triangle, this function returns .TRUE.; otherwise, it ! returns .FALSE.

! (2) REAL function TriangleArea()

-! this functions has three real formal arguments considered ! as three sides of a triangle and returns the area of this ! triangle.

! ---PROGRAM HeronFormula

IMPLICIT NONE

REAL :: a, b, c, TriangleArea DO

WRITE(*,*) 'Three sides of a triangle please --> ' READ(*,*) a, b, c

WRITE(*,*) 'Input sides are ', a, b, c

IF (TriangleTest(a, b, c)) EXIT ! exit if not a triangle WRITE(*,*) 'Your input CANNOT form a triangle. Try again' END DO

TriangleArea = Area(a, b, c)

(24)

! ---! LOGICAL FUNCTION TriangleTest() :

! This function receives three REAL numbers and tests if they form ! a triangle by testing:

! (1) all arguments must be positive, and

! (2) the sum of any two is greater than the third

! If the arguments form a triangle, this function returns .TRUE.; ! otherwise, it returns .FALSE.

! LOGICAL FUNCTION TriangleTest(a, b, c)

IMPLICIT NONE

REAL, INTENT(IN) :: a, b, c LOGICAL :: test1, test2

test1 = (a > 0.0) .AND. (b > 0.0) .AND. (c > 0.0)

test2 = (a + b > c) .AND. (a + c > b) .AND. (b + c > a) TriangleTest = test1 .AND. test2 ! both must be .TRUE. END FUNCTION TriangleTest

! ---! REAL FUNCTION Area() :

! This function takes three real number that form a triangle, and ! computes and returns the area of this triangle using Heron's formula. ! REAL FUNCTION Area(a, b, c)

IMPLICIT NONE

REAL, INTENT(IN) :: a, b, c REAL :: s

s = (a + b + c) / 2.0

Area = SQRT(s*(s-a)*(s-b)*(s-c)) END FUNCTION Area

END PROGRAM HeronFormula

Click here to download this program.

P

ROGRAM

I

NPUT AND

O

UTPUT

The following is the output from the above program.

Three sides of a triangle please --> -3.0 4.0 5.0

Input sides are -3., 4., 5.

Your input CANNOT form a triangle. Try again Three sides of a triangle please -->

1.0 3.0 4.0

Input sides are 1., 3., 4.

Your input CANNOT form a triangle. Try again Three sides of a triangle please -->

(25)

Input sides are 6., 8., 10. Triangle area is 24.

D

ISCUSSION

LOGICAL function TriangleTest() receives three REAL values. The result of the first

test condition is saved to a local LOGICAL variable test1, while the result of the second condition is saved to another LOGICAL variable test2. Since both conditions must be true to have a triangle, test1 and test2 are .AND.ed and the result goes into the function name so that it could be returned.

REAL function Area is simple and does not require further discussion. However,

please note that Area() has three formal arguments whose names are identical to the three global variables declared in the main program. By Scope Rule 3, they are diferent entities and do not cause any conficts.

 The main program has a DO-EXIT-END DO loop. In each iteration, it asks for three

real values. These values are sent to LOGICAL function TriangleTest() for testing. If the returned value is .TRUE., the input form a triangle and the control of execution exits. Then, the area is computed with REAL function Area(). If the returned value is .FALSE., this function displays a message and goes back asking for a new set of values.

C

OMMUTING

THE

C

OMBINATORIAL

C

OEFFICIENT

P

ROBLEM

S

TATEMENT

The combinatorial coefficient C(n,r) is defined as follows:

where 0 <= r <= n must hold. Write a program that keeps reading in values for n and r, exits if

both values are zeros, uses a LOGICAL function to test if 0 <= r <= n holds, and computes

C(n,r) with an INTEGER function.

S

OLUTION

! ---! This program computes the combinatorial coefficient C(n,r): !

! n!

! C(n,r) = ---! r---! x (n-r)---! !

! It asks for two integers and uses Cnr(n,r) to compute the value. ! If 0 <= r <= n does not hold, Cnr() returns -1 so that the main ! program would know the input values are incorrect. Otherwise, ! Cnr() returns the desired combinatorial coefficient.

(26)

! Note that if the input values are zeros, this program stops.

! This function receives n and r, uses LOGICAL function Test() ! to verify if the condition 0 <= r <= n holds, and uses

! Factorial() to compute n!, r! and (n-r)!.

! ---! returns .TRUE.; otherwise, it returns .FALSE.

(27)

! ---! INTEGER FUNCTION Factorial()

! This function receives a non-negative integer and computes ! its factorial.

! INTEGER FUNCTION Factorial(k)

IMPLICIT NONE

INTEGER, INTENT(IN) :: k INTEGER :: Ans, i

Ans = 1 DO i = 1, k Ans = Ans * i END DO

Factorial = Ans END FUNCTION Factorial END PROGRAM Combinatorial

Click here to download this program.

P

ROGRAM

I

NPUT AND

O

UTPUT

The following is the output from the above program.

Two integers n and r (0 <= r <= n) please 0 0 to stop -->

10 4

Your input: n = 10 r = 4 C(n,r) = 210

Two integers n and r (0 <= r <= n) please 0 0 to stop -->

7 6

Your input: n = 7 r = 6 C(n,r) = 7

Two integers n and r (0 <= r <= n) please 0 0 to stop -->

4 8

Your input: n = 4 r = 8 Incorrect input

Two integers n and r (0 <= r <= n) please 0 0 to stop -->

-3 5

(28)

r = 5 Incorrect input

Two integers n and r (0 <= r <= n) please 0 0 to stop -->

0 0

In the sample output above, please note the error messages indicating that condition 0 <= r <= n does not hold. Please also note that the program stops when the input values are 0 and 0.

D

ISCUSSION

 The function that computes the combinatorial coefcient is INTEGER function

Cnr(n,r). Since it must compute n!, r! and (n-r)!, it would be better to write a function to compute the factorial of an integer. In this way, Cnr() would just use Factorial() three times rather than using three DO-loops. Note that if the condition does not hold, Cnr() returns -1.

INTEGER function Factorial() computes the factorial of its formal argument.

LOGICAL function Test() is very simple. If condition 0 <= r <= n holds, Test

receives .TRUE.; otherwise, it receives .FALSE.

 The main program has a DO-EXIT-END DO. It asks for two integers and indicates

that the program will stop if both values are zeros. Then, Cnr() is used for computing the combinatorial coefcient. If the returned value is negative, the input values do not meet the condition and an error message is displayed. Otherwise, the

combinatorial coefcient is shown.

 Note that all three functions are internal functions of the main program.

C

OMPUTING

S

QUARE

R

OOTS

WITH

N

EWTON

'

S

M

ETHOD

P

ROBLEM

S

TATEMENT

We have discussed Newton's Method for computing the square root of a positive number. Let the given number be b and let x be a rough guess of the square root of b. Newton's method suggests that a better guess, New x can be computed as follows:

One can start with b as a rough guess and compute New x; from New x, one can generate a even

better guess, until two successive guesses are very close. Either one could be considered as the

square root of b.

Write a function MySqrt() that accepts a formal argument and uses Newton's method to

(29)

and Fortran's SQRT() function, and determines the absolute error.

S

OLUTION

! ---! This program contains a function MySqrt() that uses Newton's ! method to find the square root of a positive number. This is ! an iterative method and the program keeps generating better ! approximation of the square root until two successive

! approximations have a distance less than the specified tolerance. !

---! This function uses Newton's method to compute an approximate ! of a positive number. If the input value is zero, then zero is ! returned immediately. For convenience, the absolute value of ! the input is used rather than kill the program when the input ! is negative.

! REAL FUNCTION MySqrt(Input)

(30)

END IF

END FUNCTION MySqrt END PROGRAM SquareRoot

Click here to download this program.

P

ROGRAM

I

NPUT AND

O

UTPUT

If the input values of Begin, End and Step are 0.0, 10.0 and 0.5, the following is the output from the above program.

0.E+0, 0.E+0, 0.E+0, 0.E+0

0.5, 0.707106769, 0.707106769, 0.E+0 1., 1., 1., 0.E+0

1.5, 1.22474492, 1.2247448, 1.192092896E-7 2., 1.41421354, 1.41421354, 0.E+0

2.5, 1.58113885, 1.58113885, 0.E+0

3., 1.73205078, 1.7320509, 1.192092896E-7 3.5, 1.87082875, 1.87082863, 1.192092896E-7 4., 2., 2., 0.E+0

4.5, 2.12132025, 2.12132025, 0.E+0 5., 2.23606801, 2.23606801, 0.E+0 5.5, 2.34520793, 2.34520793, 0.E+0

6., 2.44948983, 2.44948959, 2.384185791E-7 6.5, 2.54950976, 2.54950976, 0.E+0

7., 2.64575124, 2.64575148, 2.384185791E-7 7.5, 2.73861289, 2.73861265, 2.384185791E-7 8., 2.82842708, 2.82842708, 0.E+0

8.5, 2.91547585, 2.91547585, 0.E+0 9., 3., 3., 0.E+0

9.5, 3.08220696, 3.08220696, 0.E+0 10., 3.1622777, 3.1622777, 0.E+0

D

ISCUSSION

This program has nothing special. Please refer to the discussion of Newton's method for the computation details of function MySqrt(). However, there is one thing worth to be mentioned. Since the formal argument Input is declared with INTENT(IN), it cannot be changed in function MySqrt(). Therefore, the value of the formal argument Input is copied to X and used in square root computation.

D

ESIGNING

A

G

REATEST

C

OMMON

D

IVISOR

F

UNCTION

P

ROBLEM

S

TATEMENT

We have seen Greatest Common Divisor computation. This problem uses the same idea; but

the computation is performed with a function.

S

OLUTION

(31)

! using the Euclid method. Given a and b, a >= b, the

! Euclid method goes as follows: (1) dividing a by b yields ! a reminder c; (2) if c is zero, b is the GCD; (3) if c is ! no zero, b becomes a and c becomes c and go back to

! Step (1). This process will continue until c is zero. !

! Euclid's algorithm is implemented as an INTEGER function ! GCD().

! ---PROGRAM GreatestCommonDivisor

IMPLICIT NONE INTEGER :: a, b

WRITE(*,*) 'Two positive integers please --> ' READ(*,*) a, b

WRITE(*,*) 'The GCD of is ', GCD(a, b) CONTAINS

! ---! INTEGER FUNCTION GCD():

! This function receives two INTEGER arguments and ! computes their GCD.

! INTEGER FUNCTION GCD(x, y)

IMPLICIT NONE

INTEGER, INTENT(IN) :: x, y ! we need x and y here INTEGER :: a, b, c

a = x ! if x <= y, swap x and y

b = y ! since x and y are declared with IF (a <= b) THEN ! INTENT(IN), they cannot be

c = a ! involved in this swapping process. a = b ! So, a, b and c are used instead. b = c

END IF DO

c = MOD(a, b) IF (c == 0) EXIT a = b

b = c END DO GCD = b

END FUNCTION GCD

END PROGRAM GreatestCommonDivisor

(32)

P

ROGRAM

I

NPUT AND

O

UTPUT

The following is the output from the above program.

Two positive integers please --> 46332 71162

The GCD of is 26

D

ISCUSSION

Nothing special is here. As in the previous example, since x and y are declared with INTENT(IN), their values cannot be modified and therefore their values are copies to a and b to be used in other computation.

FINDING ALL PRIME NUMBERS IN THE RANGE OF 2 AND N -

REVISITED

P

ROBLEM

S

TATEMENT

We have discussed a method for finding all prime numbers in the range of 2 and N

previously. In fact, one can design a function with an INTEGER formal argument and returns .TRUE. if the argument is a prime number. Then, it is used to test if the integers in the

range of 2 and N are integers.

S

OLUTION

! ---! This program finds all prime numbers in the range of 2 and an

! input integer.

! ---PROGRAM Primes

IMPLICIT NONE

INTEGER :: Range, Number, Count Range = GetNumber()

Count = 1 ! input is correct. start counting WRITE(*,*) ! since 2 is a prime

WRITE(*,*) 'Prime number #', Count, ': ', 2

DO Number = 3, Range, 2 ! try all odd numbers 3, 5, 7, ... IF (Prime(Number)) THEN

Count = Count + 1 ! yes, this Number is a prime WRITE(*,*) 'Prime number #', Count, ': ', Number

END IF END DO WRITE(*,*)

(33)

CONTAINS

! ---! INTEGER FUNCTION GetNumber()

! This function does not require any formal argument. It keeps ! asking the reader for an integer until the input value is greater ! than or equal to 2.

! INTEGER FUNCTION GetNumber()

IMPLICIT NONE

! This function receives an INTEGER formal argument Number. If it ! is a prime number, .TRUE. is returned; otherwise, this function ! returns .FALSE.

! LOGICAL FUNCTION Prime(Number)

IMPLICIT NONE

(34)

P

ROGRAM

I

NPUT AND

O

UTPUT

The following is the output from the above program.

What is the range ? -10

The range value must be >= 2. Your input = -10 Please try again:

0

The range value must be >= 2. Your input = 0 Please try again:

60

Prime number #1: 2 Prime number #2: 3 Prime number #3: 5 Prime number #4: 7 Prime number #5: 11 Prime number #6: 13 Prime number #7: 17 Prime number #8: 19 Prime number #9: 23 Prime number #10: 29 Prime number #11: 31 Prime number #12: 37 Prime number #13: 41 Prime number #14: 43 Prime number #15: 47 Prime number #16: 53 Prime number #17: 59

There are 17 primes in the range of 2 and 60

D

ISCUSSION

 Function GetNumber() has no formal arguments. It keeps asking the user to input

an integer that is greater than or equal to two. The valid input is returned as the function value.

 The core part of this program is LOGICAL function Prime(). It receives an INTEGER

formal argument Number and returns .TRUE. if Number is a prime number. For the working detail and logic of this function, please click here to bring you to the

example discussed previously.

T

HE

B

ISECTION

(B

OZANO

) E

QUATION

S

OLVER

P

ROBLEM

S

TATEMENT

(35)

This result provides us with a method for solving equations. If we take the midpoint of a and b,

c=(a+b)/2, and computes its function value f(c), we have the following cases:

1. If f(c) is very small (i.e., smaller than a tolerance value), then c can be considered as a root of f(x)=0 and we are done.

2. Otherwise, since f(a) and f(b) have opposite signs, the sign of f(c) is either identical to that of f(a) or that of f(b).

o If the sign of f(c) is diferent from that of f(a), then since f(a) and f(c) have opposite signs, f(x)=0 has a root in the range of a and c.

o If the sign of f(c) is diferent from that of f(b), then since f(b) and f(c) have opposite signs, f(x)=0 has a root in the range of c and b.

3. Therefore, if the original interval [a,b] is replaced with [a,c] in the first case or replaced with [c,b] in the second case, the length of the interval is reduced by half. If continue this process, after a number of steps, the length of the interval could be very small. However, since this small interval still contains a root of f(x)=0, we actually find an approximation of that root!

Write a program that contains two functions: (1) Funct() - the function f(x) and (2) Solve() - the equation solver based on the above theory. Then, reads in a and b and uses function Solve() to find a root in the range of a and b. Note that before calling Solve, your program should check if f(a)*f(b)<0 holds.

Your function Funct() is given below:

This function has a root near -0.89.

Since this process keeps dividing the intervals into two equal halves, it is usually referred to as

the bisection method. It is also known as Bozano's method.

S

OLUTION

! ---! This program solves equations with the Bisection Method. Given ! a function f(x) = 0. The bisection method starts with two values, ! a and b such that f(a) and f(b) have opposite signs. That is, ! f(a)*f(b) < 0. Then, it is guaranteed that f(x)=0 has a root in ! the range of a and b. This program reads in a and b (Left and Right ! in this program) and find the root in [a,b].

! In the following, function f() is REAL FUNCTION Funct() and ! solve() is the function for solving the equation.

! ---PROGRAM Bisection

(36)

REAL, PARAMETER :: Tolerance = 0.00001 REAL :: Left, fLeft

REAL :: Right, fRight REAL :: Root

WRITE(*,*) 'This program can solves equation F(x) = 0'

WRITE(*,*) 'Please enter two values Left and Right such that ' WRITE(*,*) 'F(Left) and F(Right) have opposite signs.'

WRITE(*,*) ! returns the value of f() at x. The following is sample function ! with a root in the range of -10.0 and 0.0. You can change the ! expression with your own function.

! ---! and Tolerance - a tolerance value such that f(Left)*f(Right) < 0 ! and find a root in the range of Left and Right.

! This function works as follows. Because of INTENT(IN), this ! function cannot change the values of Left and Right and therefore ! the values of Left and Right are saved to a and b.

(37)

! replacing a and f(a) with c and f(c) will keep a root in [a,b]. ! This process will continue until |f(c)| is less than Tolerance and ! hence c can be considered as a root.

! REAL FUNCTION Solve(Left, Right, Tolerance)

IMPLICIT NONE

REAL, INTENT(IN) :: Left, Right, Tolerance REAL :: a, Fa, b, Fb, c, Fc

a = Left ! save Left and Right b = Right

Fa = Funct(a) ! compute the function values Fb = Funct(b)

IF (ABS(Fa) < Tolerance) THEN ! if f(a) is already small Solve = a ! then a is a root

ELSE IF (ABS(Fb) < Tolerance) THEN ! is f(b) is small Solve = b ! then b is a root ELSE ! otherwise,

DO ! iterate ....

c = (a + b)/2.0 ! compute the middle point Fc = Funct(c) ! and its function value IF (ABS(Fc) < Tolerance) THEN ! is it very small? Solve = c ! yes, c is a root

EXIT

ELSE IF (Fa*Fc < 0.0) THEN ! do f(a)*f(c) < 0 ? b = c ! replace b with c Fb = Fc ! and f(b) with f(c)

ELSE ! then f(c)*f(b) < 0 holds a = c ! replace a with c

Fa = Fc ! and f(a) with f(c) END IF

END DO ! go back and do it again END IF

END FUNCTION Solve END PROGRAM Bisection

Click here to download this program.

P

ROGRAM

I

NPUT AND

O

UTPUT

The following is the output from the above program with correct input:

This program solves equation F(x) = 0

Please enter two values Left and Right such that F(Left) and F(Right) have opposite signs.

Left and Right please --> -10.0 0.0

(38)

The following output shows that the function values of the input do not have opposite signs and hence program stops.

This program solves equation F(x) = 0

Please enter two values Left and Right such that F(Left) and F(Right) have opposite signs.

Left and Right please --> -10.0 -1.0

Left = -10. f(Left) = -9.902540594E-2 Right = -1. f(Right) = -4.495930672E-2

*** ERROR: f(Left)*f(Right) must be negative ***

D

ISCUSSION

 Function Funct(x) returns the function value at x.

 The heart of this program is function Solve(). It takes three arguments Left, Right

and Tolerance and finds a root in the range of Left and Right.

 Since arguments Left and Right are declared with INTENT(IN), their values cannot

be changed. As a result, their values are copied to variables a and b.

 The function values of a and b are stored in Fa and Fb.

 If the absolute value of Fa (resp., Fb) is very small, one can consider a (resp., b) as a

root of the given equation.

 Otherwise, the midpoint c of a and b and its function value Fc are computed. If Fc is

very small, c is considered as a root.

 Then if Fa and Fc have opposite signs, replacing b and Fb with c and Fc,

respectively.

 If Fa and Fc have the same sign, then Fc and Fb must have the opposite sign. In this

case, a and Fa are replaced with c and Fc.

 Either way, the original interval [a,b] is replaced with a new one with half length.

This process continues until the absolute value of the function value at c, Fc, is smaller than the given tolerance value. In this case, c is considered a root of the given equation.

A Brief Introduction to Modules

W

HAT

IS

A

M

ODULE

?

(39)

way of packing commonly used functions into a few tool-boxes, Fortran 90 has a new capability

called modules. It has a syntactic form very similar to a main program, except for something that

are specific to modules.

S

YNTAX

The following is the syntax of a module:

MODULE module-name IMPLICIT NONE

[specification part] CONTAINS

[internal-functions] END MODULE module-name

The differences between a program and a module are the following:

 The structure of a module is almost identical to the structure of a program.

 However, a module starts with the keyword MODULE and ends with END MODULE

rather than PROGRAM and END PROGRAM.

 A module has specification part and could contain internal function; but, it does not

have any statements between the specification part and the keyword CONTAINS.

 Consequently, a module does not contains statements to be executed as in a

program. A module can only contain declarations and functions to be used by other modules and programs. This is perhaps one of the most important diference. As a result, a module cannot exist alone; it must be used with other modules and a main program

S

HORT

E

XAMPLES

Here are some short examples of modules:

 The following is a very simple module. It has the specification part and does not have

any internal function. The specification part has two REAL PARAMETERs, namely PI and g and one INTEGER variable Counter.

MODULE SomeConstants IMPLICIT NONE

REAL, PARAMETER :: PI = 3.1415926 REAL, PARAMETER :: g = 980

INTEGER :: Counter END MODULE SomeConstants

 The following module SumAverage does not have any specification part (hence no

IMPLICIT NONE); but it does contain two functions, Sum() and Average(). Please note that function Average() uses Sum() to compute the sum of three REAL numbers.

MODULE SumAverage CONTAINS

(40)

REAL, INTENT(IN) :: a, b, c Sum = a + b + c

END FUNCTION Sum

REAL FUNCTION Average(a, b, c) IMPLICIT NONE

REAL, INTENT(IN) :: a, b, c Average = Sum(a,b,c)/2.0 END FUNCTION Average

END MODULE SumAverage

 The following module DegreeRadianConversion contains two PARAMETERs, PI

and Degree180, and two functions DegreeToRadian() and RadianToDegree(). The two PARAMETERs are used in the conversion functions. Note that these parameters are global to the two functions. See scope rules for the details.

MODULE DegreeRadianConversion IMPLICIT NONE

REAL, PARAMETER :: PI = 3.1415926 REAL, PARAMETER :: Degree180 = 180.0 REAL FUNCTION DegreeToRadian(Degree) IMPLICIT NONE

REAL, INTENT(IN) :: Degree

DegreeToRadian = Degree*PI/Degree180 END FUNCTION DegreeToRadian

REAL FUNCTION RadianToDegree(radian) IMPLICIT NONE

REAL, INTENT(IN) :: Radian

RadianToDegree = Radian*Degree180/PI END FUNCTION RadianToDegree

END MODULE DegreeRadianConversion

HOW TO USE A MODULE?

Once a module is written, its global entities (

i.e.

, global PARAMETERs, global variables and

internal functions) can be made available to other modules and programs. The program or

module that wants to use a particular module must have a USE statement at its very beginning.

The USE statement has one of the following forms:

S

YNTAX

The following form is the syntax of a module:

USE module-name

USE module-name, ONLY: name-1, name-2, ..., name-n

(41)

The first indicates that the current program or module wants to use the module whose name is module-name. For example, the following main program indicates that it wants to use the content of module SomeConstants:

PROGRAM MainProgram USE SomeConstants IMPLICIT NONE ...

END PROGRAM MainProgram

Once a USE is specified in a program or in a module, every global entities of that used module (i.e., PARAMETERs, variables, and internal functions) becomes available to this program or this module. For example, if module SomeConstants is:

MODULE SomeConstants IMPLICIT NONE

REAL, PARAMETER :: PI = 3.1415926 REAL, PARAMETER :: g = 980

INTEGER :: Counter END MODULE SomeConstants

Then, program MainProgram can access to PARAMETERs PI and g and variable Counter.

However, under many circumstances, a program or a module does not want to use everything of the used module. For example, if program MainProgram only wants to use PARAMETER PI and variable Counter and does not want to use g, then the second form becomes very useful. In this case, one should add the keyword ONLY followed by a colon :, followed by a list of names that the current program or module wants to use.

PROGRAM MainProgram

USE SomeConstants, ONLY: PI, Counter IMPLICIT NONE

...

END PROGRAM MainProgram

Thus, MainProgram can use PI and Counter of module SomeConstants; but, MainProgram cannot use g!

USE with ONLY: is very handy, because it could only "import" those important and

vital information and "ignore" those un-wanted ones.

 There is a third, not recommended form, that can help to rename the names of a

module locally. If a module has a name abc, in a program with a USE, one can use a new name for abc. The way of writing this renaming is the following:

 new-name => name-in-module

For example, if one wants to give a new name to Counter of module SomeConstants, one should write:

(42)

Thus, in a program, whenever it uses MyCounter, this program is actually using Counter of module SomeConstants.

This kind of renaming can be used with ONLY: or without ONLY:.

PROGRAM MainProgram

USE SomeConstants, ONLY: PI, MyCounter => Counter IMPLICIT NONE

...

END PROGRAM MainProgram

The above example wants to use PI of module SomeConstants. In this case, when program MainProgram uses PI, it actually uses the PI of module SomeConstants. Program MainProgram also uses Counter of module SomeConstants; but, in this case, since there is a renaming, when MainProgram uses MyCounter it actually uses Counter of module SomeConstants.

Renaming does not require ONLY:. In the following, MainProgram can use all contents

of module SomeConstants. When MainProgram uses PI and g, it uses the PI and g of

module SomeConstants; however, when MainProgram uses MyCounter, it actually

uses Counter of module SomeConstants.

PROGRAM MainProgram

USE SomeConstants, MyCounter => Counter IMPLICIT NONE

...

END PROGRAM MainProgram

Why do we need renaming? It is simple. In your program, you may have a variable whose name is identical to an entity of a module that is being USEed. In this case, renaming the variable name would clear the ambiguity.

PROGRAM MainProgram

USE SomeConstants, GravityConstant => g IMPLICIT NONE

INTEGER :: e, f, g ...

END PROGRAM MainProgram

In the above example, since MainProgram has a variable called g, which is the same as PARAMETER g in module SomeConstants. By renaming g of SomeConstants, MainProgram can use variable g for the variable and GravityConstant for the PARAMETER g in module SomeConstants.

(43)

COMPILE PROGRAMS WITH MODULES

Normally, your programs and modules are stored in different files, all with filename suffix .f90.

When you compile your program, all involved modules must also be compiled. For example, if

your program is stored in a file main.f90 and you expect to use a few modules stored in files

compute.f90, convert.f90 and constants.f90, then the following command will compile your

program and all three modules, and make an executable file a.out

f90 compute.f90 convert.f90 constants.f90 main.f90

If you do not want the executable to be called a.out, you can do the following:

f90 compute.f90 convert.f90 constants.f90 main.f90 -o main

In this case, -o main instructs the Fortran compiler to generate an executable main instead of a.out.

Different compilers may have different "personalities." This means the way of compiling

modules and your programs may be different from compilers to compilers. If you have

several modules, say A, B, C, D and E, and C uses A, D uses B, and E uses A, C and D, then

the safest way to compile your program is the following command:

f90 A.f90 B.f90 C.f90 D.f90 E.f90 main.f90

That is, list those modules that do not use any other modules frst, followed by those modules that only use those listed modules, followed by your main program.

You may also compile your modules separately. For example, you may want to write and

compile all modules before you start working on your main program. The command for you to

compile a single program or module

without

generating an executable is the following:

f90 -c compute.f90

where -c means "compile the program without generating an executable." The output from Fortran compiler is a file whose name is identical to the program file's name but with a file extension .o. Therefore, the above command generates a file compute.o. The following commands compile all of your modules:

f90 -c compute.f90 f90 -c convert.f90 f90 -c constants.f90

After compiling these modules, your will see at least three files, compute.o, convert.o and constants.o.

After completing your main program, you have two choices: (1) compile your main program

separately, or (2) compile your main with all "compiled" modules. In the former, you perhaps

use the following command to compile your main program:

(44)

Then, you will have a file main.o. Now you have four .o files main.o, compute.o, convert.o and constants.o. To pull them into an executable, you need

f90 compute.o convert.o constants.o main.o

This would generate a.out. Or, you may want to use

f90 compute.o convert.o constants.o main.o -o main

so that your executable could be called main.

If you want compile your main program main.f90 with all .o files, then you need

f90 compute.o convert.o constants.o main.c

or

f90 compute.o convert.o constants.o main.c -o main

Note that the order of listing these .o files may be important. Please consult the rules

discussed

earlier

.

F

ACTORIAL

AND

C

OMBINATORIAL

C

OEFFICIENT

P

ROBLEM

S

TATEMENT

The combinatorial coefficient C(n,r) is defined as follows:

where 0 <= r <= n must hold. Write a module that contains two functions: (1) Factorial() and

(2) Combinatorial(). The former computes the factorial of its argument, while the latter uses the

former to compute the combinatorial coefficient. Then, write a main program that uses this

module.

S

OLUTION

The following is the desired module:

! ---! MODULE FactorialModule

! This module contains two procedures: Factorial(n) and

! Combinatorial(n,r). The first computes the factorial of an integer ! n and the second computes the combinatorial coefficient of two ! integers n and r.

(45)

---MODULE FactorialModule IMPLICIT NONE

CONTAINS

! ---! FUNCTION Factorial() :

! This function accepts a non-negative integers and returns its ! Factorial.

! INTEGER FUNCTION Factorial(n)

IMPLICIT NONE

INTEGER, INTENT(IN) :: n ! the argument INTEGER :: Fact, i ! result

Fact = 1 ! initially, n!=1 DO i = 1, n ! this loop multiplies Fact = Fact * i ! i to n!

END DO

Factorial = Fact END FUNCTION Factorial

! ---! FUNCTION Combinarotial():

! This function computes the combinatorial coefficient C(n,r). ! If 0 <= r <= n, this function returns C(n,r), which is computed as ! C(n,r) = n!/(r!*(n-r)!). Otherwise, it returns 0, indicating an ! error has occurred.

! INTEGER FUNCTION Combinatorial(n, r)

IMPLICIT NONE

INTEGER, INTENT(IN) :: n, r INTEGER :: Cnr

IF (0 <= r .AND. r <= n) THEN ! valid arguments ? Cnr = Factorial(n) / (Factorial(r)*Factorial(n-r)) ELSE ! no,

Cnr = 0 ! zero is returned END IF

Combinatorial = Cnr END FUNCTION Combinatorial END MODULE FactorialModule

Click here to download this program.

Here is the main program:

! ---! PROGRAM ComputeFactorial:

Referensi

Dokumen terkait

Pada proses pengiriman dan penerimaan data protokol pada ZigBee Coordinator selalu melakukan verifikasi dari data sumber pengirimn, seperti konfigurasi Coordinator ,

Strategi yang digunakan oleh perusahaan-perusahaan kapitalis untuk meningkatkan keuntungan dalam beberapa dekade terakhir secara umum telah menyebabkan penderitaan

Dari hasil simulasi frekuensi menggunakan software RiskSim Monte Carlo dengan seribu kali percobaan jangkar dijatuhkan maka diketahui bahwa peran labuh

PENGARUH MODEL PEMBELAJARAN BERBASIS MASALAH DENGAN PENDEKATAN SAINTIFIK TERHADAP KEMAMPUAN ARGUMENTASI ILMIAH SISWA SMA PADA MATERI

(DEA) menunjukkan bahwausahatani jagung di daerah penelitian belum mampu mencapai performansi tingkat efisiensi yang fullefisiensecara teknis, karena rata-rata

Gambar 4.23 Profil Muka Air memanjang sungai dengan Retensi

Teori Struktural Fungsional dalam menjelaskan perubahan-perubahan yang terjadi di masyarakat mendasarkan pada tujuh asumsi ( Lauer, 1977 ), yaitu : (1) Masyarakat harus

merancang dan membuat bisnis proses flow dan hal-hal yang berhubungan dengan sistem ERP SAP bisa berjalan lebih efektif dan sesuai. 2) Penelitian lain digunakan sebagai