Fortran 90 Tutorial_4.doc (437Kb)

  UNCTIONS AND ODULES F M ELECT THE TOPICS YOU WISH TO REVIEW S :

Functions and Modules

  

  

A Brief Introduction to Modules

  

External Functions and Interface Blocks

  

  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:

   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 type FUNCTION function-name ()

  IMPLICIT NONE

  [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.

EMANTICS S

  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. 

  UNCTIONS

  XAMPLES F E 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.

  INTEGER FUNCTION Sum(a, b, c)

  IMPLICIT NONE

  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

   2

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

  REAL FUNCTION LargerRoot(a, b, c)

  IMPLICIT NONE REAL, INTENT(IN) :: a REAL, INTENT(IN) :: b REAL, INTENT(IN) :: c REAL :: d, r1, r2 d = SQRT(b*b - 4.0*a*c) r1 = (-b + d) / (2.0*a) r2 = (-b - d) / (2.0*a)

  IF (r1 >= r2) THEN LargerRoot = r1 ELSE

  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 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.

  REAL FUNCTION GetNumber()

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

  IF (GetNumber > 0.0) EXIT WRITE(*,*) 'ERROR. Please try again.' END DO WRITE(*,*) END FUNCTION GetNumber

OMMON ROBLEMS C P 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 a = a + b END IF

  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.

  SING UNCTIONS U F

  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) + ..... ..... = ... + Average(a+b, b*c, (b+c)/a) + .....

  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().

When using a function, the values of actual arguments are passed to their corresponding formal arguments. There are some important rules:

  

INTENT(IN), its value can be changed. For writing functions, this is not a good

  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

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

  XAMPLE

  E

  practice and consequently all formal arguments should be declared with INTENT(IN) .

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

  Please continue with the next page on

  is that this

formal argument only receives a value from its corresponding actual

argument and its value cannot be changed.

   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

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

   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 an expression, it is evaluated and the result is saved into a temporary location. Then, the value in this temporary location is passed.

  A RGUMENT A SSOCIATION

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

  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.

  In the fourth WRITE, since all three actual arguments are expressions, they are evaluated and stored in temporary locations. Then, these values are passed to x, y and z.

  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.

  HERE O Y UNCTIONS O W D M F G ? 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.

  Seehe details of using external functions.

Long time ago, we mentioned the 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.

  XAMPLES E

  VERAGE T " " , A (). 

  HE EXECUTION PART CONSISTS OF THREE STATEMENTS A AN T , READ,

  ASSIGNMENT AND A HESE THREE STATEMENTS MUST BE PLACED WRITE. T BEFORE THE KEYWORD OTE ALSO THAT MUST CONTAINS. N END PROGRAM BE THE LAST LINE OF YOUR PROGRAM

.

  PROGRAM Avg

   IMPLICIT NONE REAL :: a, b, c, Mean READ(*,*) a, b, c Mean = Average(a, b, c) WRITE(*,*) a, b, c, Mean CONTAINS REAL FUNCTION Average(a, b, c)

   IMPLICIT NONE REAL, INTENT(IN) :: a, b, c Average = (a + b + c) / 3.0 END FUNCTION Average END PROGRAM Avg

  T " " L () 

G M (). T

  PROGRAM TwoFunctions

   IMPLICIT NONE

   INTEGER :: a, b, BiggerOne REAL :: GeometricMean READ(*,*) a, b BiggerOne = Large(a,b) GeometricMean = GeoMean(a,b) WRITE(*,*) 'Input = ', a, b WRITE(*,*) 'Larger one = ', BiggerOne WRITE(*,*) 'Geometric Mean = ', GeometricMean CONTAINS

   INTEGER FUNCTION Large(a, b)

   IMPLICIT NONE

   INTEGER, INTENT(IN) :: a, b

   IF (a >= b) THEN Large = a ELSE Large = b END IF END FUNCTION Large REAL FUNCTION GeoMean(a, b)

   IMPLICIT NONE

   INTEGER, INTENT(IN) :: a, b GeoMean = SQRT(REAL(a*b)) END FUNCTION GeoMean END PROGRAM TwoFunctions

  MPORTANT OTE A I N

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

  COPE ULES S R 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 The scope of an entity is the

Rule 1 program or function

  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().

  OCAL NTITIES L E

  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.

  LOBAL NTITIES G E

  Given a function f(), entities that are declared in all containing functions or the main program are said global to f(). In the above example, since variables m and n are declared in the main program, they are global to Funct1() and function Funct2(). However, variables f and g are not global to function Funct2(), since Funct1() does not contain

  Funct2(). Similarly, formal arguments u and v are not global to function Funct1().

  This comes the second scope rule:

A global entity is visible to all contained Scope functions

  

Rule 2 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

  INTEGER :: a = 1, b = 2, c = 3

  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

  I T A N C ?

  HAT F HERE RE AME ONFLICTS W

  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:

An entity declared in the scope of another

  

Scope entity is always

Rule 3 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 DO i = 1, n

  s = s + i END DO Sum = s END FUNCTION Sum END PROGRAM Scope_3

Programming Examples:

  OMPUTING UBES C C ROBLEM TATEMENT P S

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.

OLUTION S

  ! ----------------------------------------------------- ! 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

  INTEGER, INTENT(IN) :: Number intCube = Number*Number*Number

  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 Clito 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.

  ISCUSSION D

  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 M - R P ROBLEM S TATEMENT The arithmetic, geometric and harmonic means of three positive numbers are defined by the following formulas:

  

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

arithmetic, geometric and harmonic means.

OLUTION S

  ! ---------------------------------------------------------- ! 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)

  IMPLICIT NONE

  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 to download this program.

  I O The following is the output from the above program.

  ROGRAM NPUT AND UTPUT P

  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 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.

  I C ROBLEM TATEMENT P S

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.

  M AND NCH ONVERSION C

OLUTION S

  ! --------------------------------------------------------------- ! This program "contains" two REAL functions:

  ! (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 Clito download this program.

I O The following is the output from the above program

  ROGRAM NPUT AND UTPUT P

  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

  ISCUSSION D

  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.

  

ERON S ORMULA FOR OMPUTING RIANGLE REA EVISITED

H ' F C T A - R

  ROBLEM TATEMENT P S

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

  where s is the half of the perimeter length:

  

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.

OLUTION S

  ! -------------------------------------------------------------------- ! 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) WRITE(*,*) 'Triangle area is ', TriangleArea CONTAINS

  ! -------------------------------------------------------------------- ! 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 Clito 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 -->

  6.0 8.0 10.0

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

  ISCUSSION D 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 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.

  OMMUTING THE OMBINATORIAL OEFFICIENT C C C ROBLEM TATEMENT P S 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.

OLUTION S

  ! --------------------------------------------------------------- ! 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.

  !

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

  IMPLICIT NONE

  INTEGER :: n, r, Answer DO WRITE(*,*) WRITE(*,*) "Two integers n and r (0 <= r <= n) please " WRITE(*,*) "0 0 to stop --> " READ(*,*) n, r

  IF (n == 0 .AND. r == 0) EXIT WRITE(*,*) "Your input:" WRITE(*,*) " n = ", n WRITE(*,*) " r = ", r Answer = Cnr(n, r)

  IF (Answer < 0) THEN WRITE(*,*) "Incorrect input" ELSE WRITE(*,*) " C(n,r) = ", Answer END IF END DO CONTAINS ! --------------------------------------------------------------- ! INTEGER FUNCTION Cnr(n,r) ! 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)!.

  ! ---------------------------------------------------------------

  INTEGER FUNCTION Cnr(n, r)

  IMPLICIT NONE

  INTEGER, INTENT(IN) :: n, r

  IF (Test(n,r)) THEN Cnr = Factorial(n)/(Factorial(r)*Factorial(n-r)) ELSE Cnr = -1 END IF END FUNCTION Cnr ! --------------------------------------------------------------- ! LOGICAL FUNCTION Test() ! This function receives n and r. If 0 <= r <= n holds, it ! returns .TRUE.; otherwise, it returns .FALSE.

  ! --------------------------------------------------------------- LOGICAL FUNCTION Test(n, r)

  IMPLICIT NONE

  INTEGER, INTENT(IN) :: n, r Test = (0 <= r) .AND. (r <= n)

  ! --------------------------------------------------------------- ! 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 Clito download this program.

I O The following is the output from the above program

  ROGRAM NPUT AND UTPUT P