Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Contains statement

I am not understanding the importance of CONTAINS statement in fortran 90

For example

PROGRAM BLABLA

IMPLICIT NONE

INTEGER :: i,j,k

i = 1; j = 1;k =1

PRINT *, i,j,k

CALL ABC(i,j,k)

PRINT *, i,j,k

CONTAINS

    SUBROUTINE ABC(r,s,t)

    IMPLICIT NONE

    INTEGER, INTENT(IN) :: r,s
    INTEGER, INTENT(OUT) :: t

    t = r + s

   END SUBROUTINE ABC
END PROGRAM BLABLA

and one by defining subroutines outside the main program. I understand for functions, one need to specify the type of the function, but for subroutines it is not required. I am interested in understanding whether there are any additional caveats in doing so?

PROGRAM BLABLA

IMPLICIT NONE

INTEGER :: i,j,k

i = 1; j = 1;k =1

PRINT *, i,j,k

CALL ABC(i,j,k)

PRINT *, i,j,k

END PROGRAM BLABLA

SUBROUTINE ABC(r,s,t)

IMPLICIT NONE

INTEGER, INTENT(IN) :: r,s
INTEGER, INTENT(OUT) :: t

t = r + s

END SUBROUTINE ABC
like image 720
Vaidyanathan Avatar asked Mar 04 '16 23:03

Vaidyanathan


People also ask

WHAT IS A contains function?

CONTAINS is a string manipulation function that manipulates all string data types (BIT, BLOB, and CHARACTER), and returns a Boolean value to indicate whether one string is present within another.

How do you use contains in validation rule?

When using CONTAINS to compare a string with a defined set the length of the elements of the set should match the length of the string being compared. However, it's still possible to match the delimiter. An equivalent CASE statement would be longer but more reliable.


1 Answers

In both your first and second versions try changing the line

CALL ABC(i,j,k)

to

CALL ABC(i,j)

and see what happens, firstly at compile time and secondly at run time.

When you have done that, and reported back on your findings, I can turn this into a proper answer.

OK, so here's the answer, most of which you've already figured out:

In the old days, before Fortran 90, it was common for FORTRAN (everyone shouted the name in those days) programs to be compiled in separate 'units' (it still is). In your second version the program and the subroutine are in separate units and are compiled separately. There is no information available to the compiler to check that the call to the subroutine matches the subroutine signature -- that is left to the programmer to check. Call the subroutine incorrectly and almost anything can happen -- if you're lucky the program crashes or produces obviously erroneous results, if you're unlucky it produces not-obviously-erroneous-but-still-erroneous results.

If you include the source code for the subroutine in the scope of the program unit, and use the contains section, as in your first version of your program, the compiler will create an interface for the subroutine and can check that any calls made to the subroutine are formally correct. Hence the failure to compile you discovered.

The other way to have the compiler generate the interface for subroutines, and these approaches work for functions too, is to put them into a module and use the module in the program. You'll find many examples of how to do this in other Qs and As here on SO.

Putting the subroutine into a module isn't exactly the same as including it in a contains section. In the contains section the subroutine can use variables declared in the program without their being passed through the subroutine's argument list. This is rather frowned upon as poor programming practice but you do come across it in the wild.

like image 92
High Performance Mark Avatar answered Sep 21 '22 22:09

High Performance Mark