1 / 42

Chapter 7

Chapter 7. Introduction to Procedures. Introduction to Procedures. So far, all programs written in such way that all subtasks are integrated in one single large program. There is no way to code, verify and test each subtask independently before combining them to the final program.

keena
Télécharger la présentation

Chapter 7

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. Chapter 7 Introduction to Procedures

  2. Introduction to Procedures • So far, all programs written in such way that all subtasks are integrated in one single large program. • There is no way to code, verify and test each subtask independently before combining them to the final program. • Fortran has a special mechanism to do so. • Each subtask can be coded as a separate program unit called external procedure which can be compiled and tested independently. • FORTRAN External Procedures: • Subroutines • Can be invoked using CALL statement • They can return multiple results through calling arguments • Functions • Can be invoked by directly using them in expression • They return single value that is then used in the expression • Advantages of procedures: • Independent testing of subtasks • Reusable code • Isolation from unintended effects

  3. Standard FORTRAN name Beginning END Dummy arguments: variables or arrays passed from program Optional If we need to return before END similar to STOP, END Program Optional Subroutines • Subroutine is a FORTRAN procedure that is invoked by naming it in CALL statement and that retrieves its input values and return its results through an argument list. • It is an independent program that starts with SUBROUTINE and ends with END SUBROUTINE • The general form of subroutine (similar to program organization) SUBROUTINE sub_name (argument_list) … ( Declaration section) … (Execution section) … RETURN END SUBROUTINE [sub_name]

  4. Subroutines • It is compiled independently away from the program and any other subroutine. • When a program call the subroutine, the execution of the program will suspend and the procedure will execute till it reach RETURN or END SUBROUTINE and the program then resumes. • Any executable program can call a subroutine including another subroutine.

  5. Calling a subroutine • Place a CALL statement in the calling program’s code. CALL sub_name (argument_list) • The order and type of the actual arguments match the order and type of dummy arguments in the declared subroutine.

  6. z x y You can remove RETURN Example-1 • Write a program that calculates the hypotenuse of right triangle. The user should enter the first and second sides (x, y) and the program calculates and print the hypotenuse (z) PROGRAM mainProgram IMPLICIT NONE REAL :: x, y, z WRITE (*,*) 'Enter first value: ' READ (*,*) x WRITE (*,*) 'Enter second value: ' READ(*,*) y z = SQRT(x**2 + y**2) WRITE (*,*) 'Result: ', z END PROGRAM PROGRAM mainProgram IMPLICIT NONE REAL :: x, y, z WRITE (*,*) 'Enter first value: ' READ (*,*) x WRITE (*,*) 'Enter second value: ' READ(*,*) y CALL calculate(x, y, z) WRITE (*,*) 'Result: ', z END PROGRAM SUBROUTINE calculate ( first, second, output) IMPLICIT NONE REAL, INTENT(IN) :: first, second REAL, INTENT(OUT) :: output output = SQRT(first**2 + second**2) RETURN END SUBROUTINE

  7. INTENT Attribute • INTENT(IN) Dummy argument is used to pass input data to subroutine only. • INTENT(OUT) Dummy argument is used to return result to the calling program only. • INTENT(INOUT) or INTENT(IN OUT) Dummy argument is used to both pass input data to subroutine and to return result to the calling program. • You need to specify INTENT type for each argument but not for local variables of the subroutine. • This will help the compiler to know what is expected for each argument and easily discover errors. REAL, INTENT(IN) :: in in = 3 [ERROR]

  8. PROGRAM mainProgram IMPLICIT NONE INTEGER, PARAMETER:: max_Size =10 INTEGER :: i REAL, DIMENSION (max_Size) :: dat Write (*,*) 'Enter DATA set (', max_Size,' values) :' WRITE (*,*) DO i=1, max_Size READ (*,*) dat(i) END DO CALL sortArray(dat, max_Size) WRITE (*,*) ' Sorted data: ' DO i=1, max_Size WRITE (*,*) dat(i) END DO END PROGRAM Sort data in array Example-2 PROGRAM mainProgram IMPLICIT NONE INTEGER, PARAMETER:: max_Size =10 INTEGER :: i, j REAL, DIMENSION (max_Size) :: dat REAL :: temp Write (*,*) 'Enter DATA set (', max_Size,' values) :' WRITE (*,*) DO i=1, max_Size READ (*,*) dat(i) END DO DO i=max_Size, 1, -1 DO j=2, i IF (dat(j-1) > dat(j)) THEN temp = dat(j-1) dat(j-1) = dat(j) dat(j) = temp ENDIF END DO END DO WRITE (*,*) ' Sorted data: ' DO i=1, max_Size WRITE (*,*) dat(i) END DO END PROGRAM SUBROUTINE sortArray (array, arrSize) IMPLICIT NONE INTEGER, INTENT (IN):: arrSize REAL, DIMENSION(arrSize), INTENT(INOUT) :: array INTEGER :: i, j REAL :: temp DO i=arrSize, 1, -1 DO j=2, i IF (array(j-1) > array(j)) THEN temp = array(j-1) array(j-1) = array(j) array(j) = temp ENDIF END DO END DO END SUBROUTINE

  9. Variable passing in FORTRAN • Pass-by-Reference • The program passes a pointer to the memory location of actual arguments in the list which are going to be used by the subroutine to get the values of the dummy arguments. • So, pointers are sent to the subroutine not values. • Actual arguments should match the dummy arguments in number, type, and order

  10. Errors PROGRAM test REAL :: a, b, sum REAL :: c READ (*,*) a, b, c CALL adding (a, b, c, sum) WRITE (*,*) 'sum : ', sum END PROGRAM SUBROUTINE adding (x1, x2, x3, x4) REAL, INTENT(IN) :: x1, x2 INTEGER, INTENT(IN) :: x3 REAL, INTENT(OUT) :: x4 WRITE (*,*) x1, ' ', x2,' ', x3 x4 = X1 + X2 + X3 END SUBROUTINE PROGRAM test REAL :: a, b, sum REAL :: c READ (*,*) a, b, c CALL adding (a, b, c) WRITE (*,*) 'sum : ', sum END PROGRAM SUBROUTINE adding (x1, x2, x3, x4) REAL, INTENT(IN) :: x1, x2 INTEGER, INTENT(IN) :: x3 REAL, INTENT(OUT) :: x4 WRITE (*,*) x1, ' ', x2,' ', x3 x4 = X1 + X2 + X3 END SUBROUTINE ________________________________ Input : 12.6 16.5 14.9 Output: 12.6 16.5 1097754214 sum : 1.09775424E+09 ___________________ Wrong: Number of arguments does not match

  11. Exercise-1 Write a subroutine that takes three real values, add them, and return the sum. PROGRAM test REAL :: a, b, c, sum WRITE (*,*) ‘Enter three values: ’ READ (*,*) a, b, c CALL adding (a, b, c, sum) WRITE (*,*) 'sum : ', sum END PROGRAM SUBROUTINE adding (x1, x2, x3, x4) REAL, INTENT(IN) :: x1, x2, x3 REAL, INTENT(OUT) :: x4 x4 = X1 + X2 + X3 END SUBROUTINE

  12. Exercise-2 Write a subroutine that accepts three real values and return the maximum value out of the three. Don’t use the function MAX. PROGRAM test REAL :: a, b, c, maxValue WRITE (*,*) 'Enter three values: ' READ (*,*) a, b, c CALL getMax (a, b, c, maxValue) WRITE (*,*) '‘Largest Value : ', maxValue END PROGRAM SUBROUTINE getMax (x1, x2, x3, x4) REAL, INTENT(IN) :: x1, x2, x3 REAL, INTENT(OUT) :: x4 x4=x1 IF(x2>x4) THEN x4=x2 ENDIF IF(x3>x4) THEN x4=x3 ENDIF END SUBROUTINE

  13. Exercise-3 Write a subroutine that accepts three real values and return the minimum value out of the three. Don’t use the function MIN. PROGRAM test REAL :: a, b, c, maxValue WRITE (*,*) 'Enter three values: ' READ (*,*) a, b, c CALL getMax (a, b, c, maxValue) WRITE (*,*) '‘Largest Value : ', maxValue END PROGRAM SUBROUTINE getMax (x1, x2, x3, x4) REAL, INTENT(IN) :: x1, x2, x3 REAL, INTENT(OUT) :: x4 x4=x1 IF(x2<x4) THEN x4=x2 ENDIF IF(x3<x4) THEN x4=x3 ENDIF END SUBROUTINE

  14. Exercise-4 Write a subroutine that swap the values of two variables. PROGRAM test REAL :: a, b WRITE (*,*) 'Enter two values: ' READ (*,*) a, b WRITE (*,*) ' a : ', a, ' b : ', b CALL swap (a, b) WRITE (*,*) ' a : ', a, ' b : ', b END PROGRAM SUBROUTINE swap (a,b) REAL, INTENT(INOUT) :: a, b REAL :: temp temp = a a = b b = temp END SUBROUTINE

  15. Passing Arrays to subroutine • All what is needed is to send pointer to the memory location of the first element of the array. • However, the subroutine also needs to know the size of the array in order to perform operations and make sure indexes stay within bounds. • There are three ways to do so: • Explicit-Shape dummy array • Assumed-Shape dummy array • Assumed-size dummy array

  16. Explicit-Shape Dummy Array • Pass the bounds and dimensions of the array as arguments to the subroutine, then the array will be declared accordingly. • This allow the bound checker in most of FORTRAN compiler to detect out-of-bound errors. • In this method, since the shape and bounds are known, whole operations and array subsections can be used. SUBROUTINE getNewData (dat1, dat2, n) INTEGER, INTENT(IN) :: n REAL, Dimension (n), INTENT(OUT) :: dat2 REAL, Dimension (n), INTENT(IN) :: dat1 INTEGER :: i DO i=1,n dat2(i)=dat1(i)+dat1(i)**2 END DO END SUBROUTINE SUBROUTINE getNewData (dat1, dat2, n) INTEGER, INTENT(IN) :: n REAL, Dimension (n), INTENT(OUT) :: dat2 REAL, Dimension (n), INTENT(IN) :: dat1 INTEGER :: i dat2=dat1+dat1**2 END SUBROUTINE SUBROUTINE getNewData (dat1, dat2, n) INTEGER, INTENT(IN) :: n REAL, Dimension (n), INTENT(OUT) :: dat2 REAL, Dimension (n), INTENT(IN) :: dat1 INTEGER :: i dat2(1:n)=dat1(1:n)+dat1(1:n)**2 END SUBROUTINE

  17. Assumed-Shape Dummy Array • Shape is known rather than bounds. • Declared using colon as placeholder for subscripts of the arrays • The subroutine should have an explicit interface and no need to pass the array size or bounds to it. (uses modules) • Whole array operations and subsection can be used in this type MODULE test CONTAINS SUBROUTINE getNewData (dat1, dat2) REAL, Dimension (:), INTENT(OUT) :: dat2 REAL, Dimension (:), INTENT(IN) :: dat1 dat2=dat1+dat1**2 END SUBROUTINE END MODULE

  18. Assumed-Size Dummy Array • Declare the size of the array as (*) assumed size • Actual length not known by the compiler • Bounds checking, whole array operations and array sections does not work here. • This was in old FORTRAN, it should never be used in new programs SUBROUTINE getNewData (dat1, dat2, n) INTEGER, INTENT(IN) :: n REAL, Dimension (*), INTENT(OUT) :: dat2 REAL, Dimension (*), INTENT(IN) :: dat1 DO i=1,n dat2(i)=dat1(i)+dat1(i)**2 END DO END SUBROUTINE n is not the array size. It represent how many elements should be involved in the operation

  19. Exercise-5 Write a subroutine that accept array and return the sum of all its elements. PROGRAM test IMPLICIT NONE INTEGER, Parameter :: maxSize=5 REAL :: sum REAL, DIMENSION(maxSize) :: arr=(/2., -1., 5., 10., 0./) CALL sumAll (arr, maxSize, sum) WRITE(*,*) ' sum of all values: ', sum END PROGRAM SUBROUTINE sumAll (dat, n, total) INTEGER, INTENT(IN) :: n REAL, Dimension (n), INTENT(IN) :: dat REAL, INTENT(OUT) :: total INTEGER :: i total=0 DO i=1,n total=total+dat(i) END DO END SUBROUTINE

  20. Exercise-6 Write a subroutine that find the maximum value in an array (don’t use MAX function). PROGRAM test IMPLICIT NONE INTEGER, Parameter :: maxSize=5 REAL :: maxValue REAL, DIMENSION(maxSize) :: arr=(/2., -1., 5., 10., 0./) CALL getMax (arr, maxSize, maxValue) WRITE(*,*) ' maximum values: ', maxValue END PROGRAM SUBROUTINE getMax (dat, n, num) INTEGER, INTENT(IN) :: n REAL, Dimension (n), INTENT(IN) :: dat REAL, INTENT(OUT) :: num INTEGER :: i num=dat(1) DO i=2,n IF (dat(i)>num) THEN num = dat(i) END IF END DO END SUBROUTINE

  21. Exercise-7 Write a subroutine that find the minimum value in an array (don’t use MIN function). PROGRAM test IMPLICIT NONE INTEGER, Parameter :: maxSize=5 REAL :: maxValue REAL, DIMENSION(maxSize) :: arr=(/2., -1., 5., 10., 0./) CALL getMax (arr, maxSize, maxValue) WRITE(*,*) ' maximum values: ', maxValue END PROGRAM SUBROUTINE getMax (dat, n, num) INTEGER, INTENT(IN) :: n REAL, Dimension (n), INTENT(IN) :: dat REAL, INTENT(OUT) :: num INTEGER :: i num=dat(1) DO i=2,n IF (dat(i)<num) THEN num = dat(i) END IF END DO END SUBROUTINE

  22. Passing Character Variables to Subroutine • The length of the character variable is declared with (*). • It is not necessary to know the length in subroutine. • When the subroutine is called the length of the dummy argument will be the length of the actual argument in the program. • However, you can tell the size of the character at run time using the function LEN. SUBROUTINE sampleSUB (name) CHARACTER(len=*), INTENT(IN) :: name WRITE(*,*) ‘The length of the received name is: ’, LEN(name) END SUBROUTINE

  23. Error Handling in Subroutine SUBROUTINE getRES (a, b, res) IMPLICIT NONE REAL, INTENT(IN) :: a, b REAL, INTENT(OUT) :: res REAL :: temp temp = a -b res = SQRT(temp) END SUBROUTINE What does this subroutine do? What is the output if a = 1, b = 2 ? Run time error: res = -NaN Rewrite it to avoid this problem. SUBROUTINE getRES (a, b, res) IMPLICIT NONE REAL, INTENT(IN) :: a, b REAL, INTENT(OUT) :: res REAL :: temp temp = a-b IF (temp>=0) THEN res = SQRT(temp) ELSE WRITE(*,*) 'Square root of negative value in subroutine getRes' STOP ENDIF END SUBROUTINE SUBROUTINE getRES (a, b, res, error) IMPLICIT NONE REAL, INTENT(IN) :: a, b REAL, INTENT(OUT) :: res INTEGER, INTENT(OUT) :: error REAL :: temp temp = a-b IF (temp>=0) THEN res = SQRT(temp) error = 0 ELSE res = 0 error = 1 ENDIF END SUBROUTINE First solution: when square root of negative values is requested print an error and stop the program before returning form subroutine. The main program looses all data that are processed before calling the subroutine. Is there a better way? Never use STOP in any subroutine. Add an error flag that indicates the situation when the subroutine return wrong values and pass it to the main program. After returning from the subroutine, the program should check the flag and display error message for the user.

  24. Program Design • Write a program that accepts real values from the user and store them in 1-D array. The user first should be asked to enter the size of the data set he needs to enter. Then, he will be asked to enter the values. Your program should make statistics on the data that are stored in the array. The statistics will include: • Find the max value and its location in the array • Find the min value and its location in the array • Calculate the average of all values • Find the median • Calculate the standard deviation • For each one of the above subtasks write a subroutine. The main program will just accept the user inputs, store them in an array and call these five subroutines to get the results and print them to the user.

  25. Sharing Data Using Modules • Programs, Subroutine and Functions can exchange data through modules in addition to argument list. • Module is a separately compiled program unit that contains the definitions and initial values of the data we wish to share between program units. • It provides a way to share data between program units. • Modules are especially useful for sharing large volumes of data among many program and procedure units.

  26. Beginning Declaration of the data to be shared END Module Construct MODULE module_name IMPLICIT NONE SAVE INTEGER, PARAMETER :: num_Vals = 5 REAL, DIMENSION(num_Vals) :: values END MODULE

  27. Using Modules • Any program unit can make use of that share data it contains the command USE module_name • The USE command must be the first command after the program name or subroutine name. • USE association is the process of accessing information in a module using the USE statement

  28. Example - 3 PROGRAM test USE module_name IMPLICIT NONE values=(/1, 2, 3, 4, 5/) WRITE (*,*) values END PROGRAM MODULE module_name IMPLICIT NONE SAVE INTEGER, PARAMETER :: num_Vals = 5 REAL, DIMENSION(num_Vals) :: values END MODULE SUBROUTINE display USE module_name IMPLICIT NONE WRITE (*,*) values END SUBROUTINE

  29. Example - 4 PROGRAM test IMPLICIT NONE CALL display END PROGRAM MODULE module_name IMPLICIT NONE SAVE INTEGER, PARAMETER :: num_Vals = 5 REAL, DIMENSION(num_Vals) :: values=(/1,2,3,4,5/) END MODULE SUBROUTINE display USE module_name IMPLICIT NONE WRITE (*,*) values END SUBROUTINE

  30. Random Number Generator • Random number generator is a procedure that return different numbers that seem to be random. • One simple random number generator uses the following equation Ni+1 = MOD( 8121 ni + 28411, 134456) • The random number rani = ni / 134456 • n0 is call the seed of the sequence which should be entered by the user so the sequence vary from run to another. • Write a subroutine randomNum that generates and return a single number ran based on the above equations. Another subroutine (seed) should be called to get the seed value n0.

  31. Random Number Generator PROGRAM randomGenerator IMPLICIT NONE INTEGER :: n0 REAL :: num WRITE (*,*) 'Enter the seed value: ' READ (*,*) n0 CALL seed(n0) CALL randomNum(num) WRITE (*,*) num END PROGRAM SUBROUTINE seed(inSeed) USE ranValue IMPLICIT NONE INTEGER, INTENT(IN):: inSeed n = ABS(inSeed) END SUBROUTINE SUBROUTINE randomNum(ran) USE ranValue IMPLICIT NONE REAL, INTENT(OUT):: ran n = MOD(8121*n+28411, 134456) ran = REAL(n)/134456 END SUBROUTINE MODULE ranValue IMPLICIT NONE SAVE INTEGER :: n END MODULE

  32. Full Program • Now, modify the main program so that it prints 10 random numbers. • Then, make it generates 1000 numbers and calculate their average. PROGRAM randomGenerator IMPLICIT NONE INTEGER :: n0 REAL :: num WRITE (*,*) 'Enter the seed value: ' READ (*,*) n0 CALL seed(n0) CALL randomNum(num) WRITE (*,*) num END PROGRAM SUBROUTINE randomNum(ran) USE ranValue IMPLICIT NONE REAL, INTENT(OUT):: ran n = MOD(8121*n+28411, 134456) ran = REAL(n)/134456 END SUBROUTINE SUBROUTINE seed(inSeed) USE ranValue IMPLICIT NONE INTEGER, INTENT(IN):: inSeed n = ABS(inSeed) END SUBROUTINE MODULE ranValue IMPLICIT NONE SAVE INTEGER :: n END MODULE PROGRAM randomGenerator IMPLICIT NONE INTEGER :: n0, i REAL :: num, sum=0, Avg WRITE (*,*) 'Enter the seed value: ' READ (*,*) n0 CALL seed(n0) WRITE (*,*) ' 10 random numbers : ' DO i=1, 10 CALL randomNum(num) WRITE (*,*) num END DO DO i=1, 1000 CALL randomNum(num) sum = sum +num END DO Avg = sum / 1000 WRITE (*,*) ' The average of 1000 random numbers is: ', Avg END PROGRAM

  33. FORTRAN FUNCTION • FORTRAN Function is a procedure that returns single output which can be, number, logical value, character string or an array. • In contrast to routines, functions can be used and combined with expressions. • Function types: • Intrinsic functions Built into the FORTRAN language (e.g. SIN(x), MAX(a,b)) • User-defined functions (function subprograms) Defined by a programmer to meet specific needs not addressed by intrinsic functions and they are used in expressions like intrinsic function.

  34. Dummy arguments: variables or arrays passed from program. Can be blank but with parenthesis Standard FORTRAN name Beginning The return value Optional If we need to return before END END Optional Function Construct FUNCTION functionName (argument_List) … (Declaration Section must declare type of functionName) … (Execution section) functionName = expr RETURN END FUNCTION [ functionName ] FUNCTION myMax (a , b) IMPLICIT NONE REAL :: myMax REAL, INTENT(IN) :: a, b IF(a>=b) THEN myMax = a ELSE myMax=b END IF END FUNCTION

  35. Declaring Function Type FUNCTION myMax(a,b) REAL :: myMax OR REAL FUNCTION myMax(a,b) FUNCTION myMax (a , b) IMPLICIT NONE REAL :: myMax REAL, INTENT(IN) :: a, b IF(a>=b) THEN myMax = a ELSE myMax=b END IF END FUNCTION REAL FUNCTION myMax (a , b) IMPLICIT NONE REAL, INTENT(IN) :: a, b IF(a>=b) THEN myMax = a ELSE myMax=b END IF END FUNCTION

  36. Exercise-8 Write a program that call the function quadf that calculates and returns the value of the quadratic equation. In the main program the user will be asked to enter the three coefficients a, b, c and the evaluation value x. All of these four values will be sent as arguments to the function quadf. Finally, the program will print the result returned by the function.

  37. PROGRAM quadraticFunction IMPLICIT NONE REAL :: quadf REAL :: a, b, c, x, f WRITE (*,*) 'Enter the three coefficients a,b,c : ' READ (*,*) a,b,c WRITE (*,*) 'Enter the evaluation value x: ' READ (*,*) x f = quadf(x, a, b, c) WRITE (*,*) 'The quadratic result: ', f END PROGRAM FUNCTION quadf(x,a,b,c) IMPLICIT NONE REAL :: quadf REAL, INTENT(IN) :: x,a,b,c quadf=a*x**2+b*x+c END FUNCTION REAL FUNCTION quadf(x,a,b,c) IMPLICIT NONE REAL, INTENT(IN) :: x,a,b,c quadf=a*x**2+b*x+c END FUNCTION

  38. Unintended Side Effects in Functions • Side effect happen when the function change the values of the input arguments in the program. • The function should produce single output and it should have no side effects. • It should never modify its input arguments. • If you need a function that produce more than one result then, use subroutine instead. • Always declare input arguments with INTENT(IN) to avoid side effects.

  39. Exercise-9 • The sinc function is defined by the equation: sinc(x)=sin(x)/x • It is easy to implement but consider x equal or very close to zero. • Modify the equation to be: IF |x|> Epsilon sinc(x)=sin(x)/x Else sinc=1 • Epsilon is very small real number that is chosen to ensure that the division does not cause divide by zero. A good value of Epsilon is 1.0E-30

  40. PROGRAM getSINC IMPLICIT NONE REAL :: sinc REAL :: x WRITE (*,*) 'Enter a number to evaluate with SINC : ' READ (*,*) x WRITE(*,*) 'THe value is: ', sinc(x) END PROGRAM REAL FUNCTION sinc(x) IMPLICIT NONE REAL, PARAMETER :: eps=1.0E-30 REAL, INTENT(IN) :: x IF (ABS(x)>eps) THEN sinc=SIN(x)/x ELSE sinc=1 END IF END FUNCTION

  41. Tutorial Write a subroutine to compute the average of all the elements in a matrix. Use a SUBROUTINE AND A MODULE within a program to ask the user for a matrix, and compute its average. Add one more subroutine to find the maximum value in the matrix and its location PROGRAM tutorial_on_subroutines USE tut IMPLICIT NONE INTEGER :: i, j WRITE(*,*) 'Enter the elements of the matrix A (3x3)' READ (*,*) A CALL find_mean WRITE (*,*) 'The mean of your matrix = ', A_mean END PROGRAM SUBROUTINE find_mean USE tut IMPLICIT NONE INTEGER :: i, j REAL :: total=0.0 DO i=1,3 DO j=1,3 total = total + A(i,j) END DO END DO A_mean = total / 9.0 END SUBROUTINE MODULE tut IMPLICIT NONE REAL, DIMENSION (3,3) :: A REAL:: A_mean END MODULE

More Related