User-Defined Functions • In addition to having the library functions available, the FORTRAN programmer may write her own functions. • Each such function begins with a function header as follows: ftype FUNCTION fname ( dummy-argument-list ) • The dummy arguments are used to receive values which are passed into the function from the "outside". • The single result of the function, which is of ftype, is passed back (returned) to the "outside" through the function's name, fname • Somewhere within the body of the function, a value must be assigned to the function name: fname = expression • If a user defined function does not have any arguments, an empty pair of parentheses () must appear in the FUNCTION header statement after the function name as follows: ftype FUNCTION fname () • When the function is completed, it should execute a RETURN statement. Also, the physical end of the function should be marked by an END statement. FORTRAN Programming User Defined Functions Page 1 REAL FUNCTION DOAREA (R) C Computes the area of a circle with radius R. C Precondition : R is defined. C Postcondition: Function result is the circle area. C Argument declaration REAL R C Local declaration REAL PI PARAMETER (PI = 3.14159) C Define function result DOAREA = PI * R ** 2 C Exit function RETURN END C -------------------------------------------------------REAL FUNCTION DOCIRC (R) C Computes the circumference of a circle with radius R. C Precondition : R is defined. C Postcondition: Function result is the circle circumference. C Argument declaration REAL R C Local declaration REAL PI PARAMETER (PI = 3.14159) C Define function result DOCIRC = 2 * PI * R C Exit function RETURN END FORTRAN Programming User Defined Functions Page 2 Function Syntax: ftype FUNCTION fname ( dummy-argument-list ) interface-section description of dummy arguments declaration-of-dummy-arguments declaration-of-local-parameters definition-of-local-parameters declaration-of-local-variables : function-body : fname = expression : RETURN END Dummy Arguments • The programmer must be careful to declare the dummy arguments within the function. Local Variables and Parameters: • In addition to the dummy arguments, other variables and parameters may be used within the function. • These are local to the function and are not known to the main program. • The programmer must be careful to declare these local variables and parameters within the function. FORTRAN Programming User Defined Functions Page 3 Comments Within Functions • The first few comment lines in a function should cover the following items: Ò Describe what the function does Ò Describe any preconditions which must be true before the function is called Ò Describe any post conditions which are true after the function has completed execution Ò Identify and describe each dummy argument • These comments are useful to anyone wishing to use this function in another program. • Additional comments should be included to identify the author, to describe each additional symbolic-name used in the function (local parameters, local variables, etc.) and to summarize each major step in the function's algorithm. • This is done in a manner similar to a main program Function Usage • A user defined (programmed) function is referenced (called) in the same manner as a library function • The program unit in which the function is referenced (used) must also contain a declaration statement to declare the type of the function that is being referenced. Actual Arguments • When a function is referenced; the constants, variables, and/or expressions which are used to pass values into the function are referred to as the actual arguments. FORTRAN Programming User Defined Functions Page 4 • These should not be confused with the dummy arguments which are the variables used within the function definition to receive the values being passed. FORTRAN Programming User Defined Functions Page 5 C C C C REAL FUNCTION ROUND(X, PLACES) Rounds the value of X. Pre : X is defined and PLACES is greater than or equal to zero. Post: Function result is X rounded to PLACES decimal points. C Argument Declarations. REAL X INTEGER PLACES C Local Declarations. REAL TEMPX, POWER IF (PLACES .GE. 0) THEN POWER = 10.0 ** PLACES TEMPX = X * POWER ROUND = NINT(TEMPX) / POWER ELSE PRINT *, 'Negative argument for PLACES -- no rounding', + ' done' ROUND = X END IF C Exit function. RETURN END FORTRAN Programming User Defined Functions Page 6 INTEGER FUNCTION ENTER (NMIN, NMAX) C Returns the first data value read between NMIN and NMAX. C Pre : NMIN is less than or equal to NMAX. C Post: Function result lies between NMIN and NMAX. C Argument Declarations INTEGER NMIN, NMAX C Declarations. INTEGER N LOGICAL BETWEN C Initially assume an integer between NMIN and NAMX is not entered. BETWEN = .FALSE. C Keep reading until an integer between NMIN and NMAX is entered. DO WHILE (.NOT. BETWEN) PRINT *, 'Enter an integer between ', + NMIN, ' and ', NMAX READ *, N BETWEN = (N .GE. NMIN) .AND. (N .LE. NMAX) END DO C Define result. ENTER = N C Exit subroutine. RETURN END INTEGER FUNCTION FACTRL (N) C Computes the factorial of N. C Pre : N is greater than or equal zero. C Post: Function result is N!. C Argument Declarations. INTEGER N C Local Declarations. INTEGER I, PRODUC C Accumulate partial products in PRODUC. PRODUC = 1 DO 10 I = N, 2, -1 PRODUC = PRODUC * I 10 CONTINUE C Define function result. FACTRL = PRODUC C Exit function. RETURN END FORTRAN Programming User Defined Functions Page 7 Validating Function Arguments (Defensive Programming) • It is good programming style for a function to check the validity of its arguments. • A function should respond to an invalid argument by printing an error message and attempting to return a usable result. Usage Note • A user defined function may reference library functions and other user defined functions; • However, in FORTRAN 77, a function may not reference itself (be recursive) either directly or indirectly. PROGRAM CIRCLE C Finds and prints the area and circumference of a circle. C The program user enters the circle radius and units of C measurement. C Declarations REAL RADIUS, AREA, CIRCUM CHARACTER *12 UNITS REAL DOAREA, DOCIRC C Read the value of RADIUS and UNITS PRINT *, 'Enter units (enclosed in apostrophes)' READ *, UNITS PRINT *, 'Enter radius (in ', UNITS, ')' READ *, RADIUS C Find the area AREA = DOAREA(RADIUS) C Find the circumference CIRCUM = DOCIRC(RADIUS) C Print the values of AREA and CIRCUM PRINT *, 'The area is ', AREA, ' square ', UNITS PRINT *, 'The circumference is ', CIRCUM, ' ', UNITS STOP END C ---------------------------------------------------------C Insert function DOAREA here C ---------------------------------------------------------- FORTRAN Programming User Defined Functions Page 8 C Insert function DOCIRC here FORTRAN Programming User Defined Functions Page 9 Argument Correspondence Modularity • User written functions are independent program modules, or subprograms. • A subprogram may not be executed by itself; it must be referenced (called) by a main program or another subprogram. Function Positioning • User written functions should be placed after the END statement of the main program in the source code file. Name Independence • Dummy arguments, local variable names, and local parameter names used within a function are unrelated to any other uses of these names in any other program unit, function or main program. Argument List Correspondence • The number of actual arguments in a function reference must be the same as the number of dummy arguments in the function definition. • Also, the type of each actual argument used in a function reference must be the same as the type of the corresponding dummy argument. • Again, be very careful with constants, 5 is not REAL and 5.0 is not INTEGER. Side Effects • It is poor programming practice for a function to change the value of any of its dummy arguments. FORTRAN Programming User Defined Functions Page 10 • Any such undesirable change is called a side effect. FORTRAN Programming User Defined Functions Page 11 PROGRAM FUNCAL C Illustrates a function call. C Declarations. INTEGER NUM, FACT INTEGER FACTRL PRINT *, 'Enter an integer between 0 and 10' READ *, NUM IF (NUM .GE. 0) THEN FACT = FACTRL (NUM) PRINT *, 'The factorial of ', NUM, ' is ', FACT ELSE PRINT *, 'The factorial of a negative number is ', + 'undefined.' ENDIF C Exit program. STOP END C -----------------------------------------------------------INTEGER FUNCTION FACTRL (N) C Computes the factorial of N. C Pre : N is greater than or equal zero. C Post: Function result is N!. C Argument Declarations. INTEGER N C Local Declarations. INTEGER I, PRODUC C Accumulate partial products in PRODUC. PRODUC = 1 DO 10 I = N, 2, -1 PRODUC = PRODUC * I 10 CONTINUE C Define function result. FACTRL = PRODUC C Exit function. RETURN END FORTRAN Programming User Defined Functions Page 12 Combinations: The number of ways to in which r items can be selected from a collection of n items without regard to order: n! C( n,r ) r!(n r)! PROGRAM COMBIN C Computes the number of combinations of N items taken R at a C time. C Declarations. INTEGER N, R, C INTEGER FACTRL PRINT *, 'Enter number of items in the collection:' READ *, N PRINT *, 'Enter number of items to be selected:' READ *, R IF (R .LE. N) THEN C = FACTRL(N) / (FACTRL(R) * FACTRL(N-R)) PRINT *, 'The number of combinations is ', C ELSE PRINT *, 'Items to be selected cannot exceed total ', + 'items' END IF C Exit program. STOP END C --------------------------------------------------------------INTEGER FUNCTION FACTRL (N) C Computes the factorial of N. C Pre : N is greater than or equal to zero. C Post: Function result is N!. Actual code for factorial as before C Exit function. RETURN END FORTRAN Programming User Defined Functions Page 13 Single-Statement Functions: Single Statement Functions • If a function can be written as a single assignment statement, then the function may be defined within the referencing program unit as follows: declaration-of-parameters definition-of-parameters : ftype fname (function name declaration) dummy-argument-declarations : fname ( dummy-argument-list ) = expression • Examples REAL Z REAL HALF HALF(X) = X/2 and REAL X, Y, C REAL HYPOT, SQUARE SQUARE(X) = X * X HYPOT(X, Y) = SGRT(SQUARE(X) + SQUARE(Y)) • If a function is declared in this manner, then the statement which assigns a value to the function name must come before any other executable statement within the program unit. • In this situation, the dummy arguments may also be used as regular variables within the program unit. FORTRAN Programming User Defined Functions Page 14 PROGRAM NEWTON C Finds a root of an equation using Newton's method. C Declarations REAL EPSLON INTEGER MAXGES PARAMETER (EPSLON = 0.00001, MAXGES = 100) REAL XLAST, XNEXT INTEGER NUMGES C Functions REAL F, FPRIME, X F(X) = 5 * X * X * X - 2 * X * X + 3 FPRIME(X) = 15 * X * X - 4 * X C Read the initial guess into XNEXT. PRINT *, 'Enter initial guess for a root:' READ *, XNEXT C Compute successive guesses. DO 20 NUMGES = 1, MAXGES XLAST = XNEXT XNEXT = XLAST - F(XLAST) / FPRIME(XLAST) IF (ABS(XNEXT - XLAST) .LT. EPSLON) THEN PRINT 5, 'The approximate root is ', XNEXT PRINT 5, 'The function value is ', F(XNEXT) 5 FORMAT (1X, A, E17.11) PRINT 15, NUMGES, ' guesses were made' 15 FORMAT (1X, I3, A) C Exit from the loop GOTO 99 END IF 20 CONTINUE C Normal exit -- display a message that a root was not found. PRINT 25, 'Root not found before ', MAXGES, ' guesses.' 25 FORMAT (1X, A, I3, A) C Continuation point after loop exit 99 CONTINUE STOP END FORTRAN Programming User Defined Functions Page 15 LOGICAL Functions • A function may be of type LOGICAL and return a logical value. • Example: REAL NUM LOGICAL POSTIV POSTIV(NUM) = (NUM .GT. 0.0) ... IF (POSTIV(X)) THEN ... GOTO Statement • The GOTO statement is used in FORTRAN to cause an immediate transfer of control from the GOTO statement to another statement within the FORTRAN program. • The label in the GOTO statement must match a label on some other executable FORTRAN statement within the program. Programming Style • The use of the GOTO statement is generally considered to be harmful. • Code written with numerous GOTO statements is referred to a spaghetti code. FORTRAN Programming User Defined Functions Page 16 Defining a Subroutine Subroutine Definition • A subroutine is a separate program module whose execution may return any number of results (including zero) to the calling program. • A subroutine is defined in much the same manner as a function is declared • A subroutine does not return a value through its name as a function does, so there is no need to give the subroutine's name a type nor to assign it a value within the body of the subroutine. SUBROUTINE TABHED (STRNTH) C Displays the heading for the rebar table. C Argument Declarations. REAL STRNTH PRINT *, ' Joe Bob''s Steel Company' PRINT *, ' Rebar load chart' PRINT *, 'For bars with a steel strength of ', STRNTH, + ' psi' PRINT * PRINT *, 'Bar Cross-sectional Max. Load' PRINT *, 'Number Area (sq. in.) (lbs.)' PRINT *, '----------------------------' C Exit subroutine. RETURN END FORTRAN Programming User Defined Functions Page 17 SUBROUTINE BREAK (X, WHOLE, FRAC) C Breaks a whole number into its whole and fractional parts. C Input Argument. C X - The value to be split (REAL). C Output Arguments. C WHOLE - The whole part of X (INTEGER). C FRAC - The fractional part of X (REAL). C Argument Declarations. REAL X, FRAC INTEGER WHOLE C Define results. WHOLE = INT(X) FRAC = X - REAL(WHOLE) C Exit subroutine. RETURN END Subprogram Definition format: SUBROUTINE sname ( dummy-argument-list ) interface section description of dummy arguments declaration of dummy arguments declaration-of-local-parameters definition-of-local-parameters declaration of local variables : subroutine body : RETURN END FORTRAN Programming User Defined Functions Page 18 Dummy Arguments • The dummy arguments are used to both pass values into the body of the subroutine and to pass results back to program unit using the subroutine. • Dummy arguments are optional. A subroutine may be written without any arguments Input Argument • A dummy argument which is used only to pass a value into a subroutine (or function) and is not changed by the subroutine (or function) is called in input argument. Output Argument: • A dummy argument which is used only to pass a value out of a subroutine is called an output argument. • It is assigned a value in the subroutine and may be used (accessed or reassigned) in the subroutine after the initial assignment. • Output Arguments should not be used with functions. Input/Output Argument • A dummy argument which is used both to pass a value into a subroutine and to pass a result out of the subroutine is called an input/output argument. • Input/output arguments should not be used with functions. FORTRAN Programming User Defined Functions Page 19 SUBROUTINE ORDER (S, L) C Arranges its arguments in numerical order. C Input/Output Arguments. C S - Smaller number after execution of ORDER. C L - Larger number after execution of ORDER. C Argument Declarations. REAL S, L C Local Declarations. REAL TEMP C Compare S and L and switch if necessary. IF (S .GT. L) THEN TEMP = S S=L L = TEMP END IF C Exit subroutine. RETURN END Documentation • A subroutine should be documented (commented) in much the same manner as a function or a main program • The purpose of the subroutine, its preconditions and post conditions, and the description of each of its dummy arguments should be provided at the beginning in an "interface" section. • Additional comments should be included to identify the author, to describe each additional symbolic-name used in the subroutine (local parameters, local variables, etc.) and to summarize each major step in the subroutine's algorithm. FORTRAN Programming User Defined Functions Page 20 Calling a Subroutine Calling A Subroutine • A function is used by simply referencing it in an expression, but a subroutine is executed (called) by using a CALL statement. CALL subroutine-name ( actual-argument-list ) Argument Correspondence • Just as with functions the i-th actual argument in a subroutine call corresponds to the i-th dummy argument in the subroutines declaration. • The corresponding actual arguments and dummy arguments should be of the same data type. Top-Down Design and Structure Charts Functions or Subroutines? • A functions should be used to implement a subprogram when the subprogram returns a single value and does not modify any of its arguments; • otherwise, a subroutine should be used. Structure Chart • This is a program documentation aid which provides a graphical representation of both the flow of control and the flow of data between the main program and its subprograms. FORTRAN Programming User Defined Functions Page 21 PROGRAM REBAR2 C Prints a table of maximum tensile load on rebars C using subprograms C Declarations INTEGER FIRBAR, LASBAR PARAMETER (FIRBAR = 2, LASBAR = 11) REAL STRNTH C Read steel strength PRINT *, 'Enter steel tensile strength (in psi)' READ *, STRNTH C Display table heading. CALL TABHED (STRNTH) C Display table body. CALL TABBOD (STRNTH, FIRBAR, LASBAR) C Exit program STOP END C --------------------------------------------------C Insert subroutines TABHED and TABBOD here FORTRAN Programming User Defined Functions Page 22 SUBROUTINE TABBOD (STRNTH, FIRBAR, LASBAR) C Displays a table showing the rebar number, cross-sectional C area, and maximum load for each rebar. C Precondition : STRNTH, FIRBAR, and LASBAR are defined and C FIRBAR <= LASBAR. C Postcondition: Table body is displayed. C Input Arguments C STRNTH - steel tensile strength C FIRBAR - first rebar number C LASBAR - last rebar number C Argument Declarations REAL STRNTH INTEGER FIRBAR, LASBAR C Local Declarations INTEGER BARNUM REAL AREA, LOAD, RADIUS, DOAREA C Display table body DO 10 BARNUM = FIRBAR, LASBAR RADIUS = BARNUM / 16.0 AREA = DOAREA(RADIUS) PRINT 5, BARNUM, AREA, LOAD 5 FORMAT (1X, I6, 13X, F6.2, 14X, F8.0) 10 CONTINUE C Exit subroutine RETURN END C ----------------------------------------------C Insert function DOAREA here. FORTRAN Programming User Defined Functions Page 23 Drivers • Before a subprogram is made a part of a large program, it should be tested by cling (referencing) it from a small main program designed specifically to test the subprogram. • This test program or driver should check every feature of the subprogram including all error messages for invalid argument values. Bottom-up Testing • The process of pretesting each subprogram with a driver program before it is added into the system is called bottom-up testing. Stub • A stub is a dummy subprogram (usually including a print statement) used in place of the actual subprogram. • Stubs are used to check program control flow even before the actual subroutines have been completed. Top-down Testing: • The process of testing the main system by using stubs for the uncompleted subprograms is called top-down testing. Use Trace: • When debugging a program system, every subprogram should print its name and all of its inputs when it is executed. • Every function should print its output just before finishing and every subroutine should print all of its outputs (Input/Output Arguments) just before finishing. FORTRAN Programming User Defined Functions Page 24 Common Programming Errors • Be sure that each user defined function is assigned a value before the RETURN statement is executed ( fname = expression ). • Be sure to declare the data type of each user defined function in every program unit where the function is referenced (used). • Main program variables may not be accessed in subprograms unless they are passed as arguments to the subprogram, and local variables used within subprograms cannot be accessed in the calling program unit. • Be sure that the actual arguments and the dummy arguments for all subprogram usage's agree in number and data type. • Remember, misspelled subprogram names will not be detected until the Linker tries to "bolt" all of the pieces together. FORTRAN Programming User Defined Functions Page 25