Silverfrost Forums

Welcome to our forums

Array variables

3 Dec 2014 3:19 #15183

The following code was originally written for the Watcom compiler and I assume worked ok:

           SUBROUTINE RECTANG(I)
 
            IMPLICIT NONE
            COMMON T1,N,NM_N,M,NM_M,FN,MI,FS,MF,NF,NI,NM_NI,NM_MI,NIF,MIF,TF
            INTEGER MI(20,20),NI(20),FS(50,30),MIF(20,20),NIF(20)
            INTEGER NF(30),MF(20,30),TF(40)
            DOUBLE PRECISION N(30),M(20,30)
            CHARACTER *40 NM_N(30),NM_M(30),FN(50)*30,T1(40)
            CHARACTER *40 NM_NI(20),NM_MI(20)
            COMMON /POCK/P,PNI,PI,NM_P,NM_PNI,NM_PI,PF,PNIF,PIF
            CHARACTER *40 NM_P(10),NM_PNI(3),NM_PI
            INTEGER PI(2,31),PNI(2,3),PF(2,31,10),PNIF(2,3),PIF(2,31)
            DOUBLE PRECISION P(2,31,10)

           DOUBLE PRECISION LENGTH,WIDTH,C_RAD,PT_MAX
           CHARACTER *60 CP
           DOUBLE PRECISION L1,L2,PIE,R_L,APH_R,HP,DTEMP
           INTEGER I,J1,J2,J3

           PRINT*,'SUBROUTINE RECTANG'
           
           HP(L1,L2) = DSQRT(L1*L1+L2*L2)
 
           PIE = DACOS(-1D0)
 
           PNI(I,2) = 8
           PNIF(I,2) =2
           PNI(I,3) = 1
           PNIF(I,3) =2

As you can see the variable 'HP' is defined without any array parameters yet in the code it is clearly used as an array variable.

The Silverfrost compiler objects to the code, does any one have any information which may resolve the problem please?

3 Dec 2014 4:43 #15184

No, the code looks like it has been corrupted. Look for the places where HP is used (presumably without indexes). If HP is an array then it needs a DIMENSION and its indexes ought to be integer values. My guess is that it will be used as a scalar and that it should appear as a scalar in the assignment.

3 Dec 2014 9:29 #15186

Mike,

There has been a similar discussion recently here:

https://forums.silverfrost.com/Forum/Topic/2612

There is a chance that your HP is a statement function. It is a bit unusual that there is a PRINT first, but Watcom is a law unto itself, and perhaps HP means 'hypotenuse' or 'hypotenuse (by) Pythagorus' L1 and L2 are DOUBLE PRECISION so unlikely to be array subscripts, don't you agree?

Eddie

3 Dec 2014 10:06 #15187

Indeed, HP appears to be a 'statement function'. One could guess that someone trying to troubleshoot the program added a print statement at the beginning of the subroutine executable statements, but made a slip.

Just move the PRINT statement down one line (blank lines do not count).

4 Dec 2014 6:52 #15188

Statement function for calculating a hypotenuse. Just move the print statement as suggested.

With all these kinds of errors you can get a list of what variables are in the code using /LIST /DUMP. This will produce a listing file showing you that it is a function not a variable.

There was a time when obtaining a variable dump with the code listing was a standard procedure but it seems to not be a popular debugging technique now.

5 Dec 2014 5:42 #15191

The statement function HP = must proceed executable statements

           SUBROUTINE RECTANG(I) 
   
             IMPLICIT NONE 
             COMMON T1,N,NM_N,M,NM_M,FN,MI,FS,MF,NF,NI,NM_NI,NM_MI,NIF,MIF,TF 
             INTEGER MI(20,20),NI(20),FS(50,30),MIF(20,20),NIF(20) 
             INTEGER NF(30),MF(20,30),TF(40) 
             DOUBLE PRECISION N(30),M(20,30) 
             CHARACTER *40 NM_N(30),NM_M(30),FN(50)*30,T1(40) 
             CHARACTER *40 NM_NI(20),NM_MI(20) 
             COMMON /POCK/P,PNI,PI,NM_P,NM_PNI,NM_PI,PF,PNIF,PIF 
             CHARACTER *40 NM_P(10),NM_PNI(3),NM_PI 
             INTEGER PI(2,31),PNI(2,3),PF(2,31,10),PNIF(2,3),PIF(2,31) 
             DOUBLE PRECISION P(2,31,10) 

            DOUBLE PRECISION LENGTH,WIDTH,C_RAD,PT_MAX 
            CHARACTER *60 CP 
            DOUBLE PRECISION L1,L2,PIE,R_L,APH_R,HP,DTEMP 
            INTEGER I,J1,J2,J3 

            HP(L1,L2) = DSQRT(L1*L1+L2*L2)       ! statement function
      
            PRINT*,'SUBROUTINE RECTANG' 
             
            PIE = DACOS(-1D0) 
   
            PNI(I,2) = 8 
            PNIF(I,2) =2 
            PNI(I,3) = 1 
            PNIF(I,3) =2 
5 Dec 2014 8:04 #15192

John-Silver

The point is that this is the definition of the function HP. It is old Fortran that is depreciated but still works.

5 Dec 2014 11:47 #15193

The confusion expressed by John Silver reinforces the wisdom of the Fortran 95 standard's authors, when they say (in Section B.2 Obsolescent features: B.2.3, Statement functions):

Statement functions are subject to a number of non-intuitive restrictions and are a potential source of error since their syntax is easily confused with that of an assignment statement.

Table 2.1 of the standard shows the order in which statements may appear, and clearly shows that statement functions must come before executable statements. Whether to move the PRINT statement a line down or to move the statement function definition a line up is subject to the programmer's whim, and the compiler will be indifferent regarding which line was moved.

5 Dec 2014 12:41 #15194

Thanks to everyone for the information

5 Dec 2014 3:00 #15195

Just to clear any incorrect conclusions that could be reached from what has been written in this thread, I installed the OpenWatcom F77 compiler on Win32, and ran it on the code posted by Mike.Smartcam. It said:

Open Watcom FORTRAN 77/32 Optimizing Compiler Version 1.9
Portions Copyright (c) 1984-2002 Sybase, Inc. All Rights Reserved.
Source code is available under the Sybase Open Watcom Public License.
See http://www.openwatcom.org/ for details.
asf.f(22): *ERR* ST-02 statement function definition appears after first executable statement
5 Dec 2014 5:11 #15196

If non-intuitiveness is the criterion to discard anything, perhaps we should dispense with most programming languages!

In my view, part of the problem is that as a language that occupies a specialist niche, Fortran isn't taught anymore, and computer science bookshelves aren't full of books on it (like McCracken or Etter), most people who program in it are largely or wholly self-taught, and some worthy programs were in any case written to match the facilities of a particular computer and compiler that now only exists in museums. Slef-teaching is an important part of learning, but it often results in an incomplete knowledge of a particular subject.

There isn't the slightest bit of non-intuitiveness about the local definition of an inline function with its scope limited to the routine it is defined in. I know that sooner or later I may fall over the definition of a statement function, which is why I would always add a comment or two explaining what it is and does.

Incidentally, what is the assumed type of the result of a statement function if IMPLICIT NONE is in use. I imagine that this is an obstacle to its use in recent-standard compliant use.

Eddie

5 Dec 2014 9:24 #15198

What is the assumed type of the result of a statement function if IMPLICIT NONE is in use? The function name must appear in a type declaration statement, in the same way that the name of any variable must be given a type.

5 Dec 2014 9:55 #15199

Would that be

DOUBLE PRECISION HP
HP(L1,L2) = DSQRT(L1*L1+L2*L2)

or

DOUBLE PRECISION HP(L1,L2) = DSQRT(L1*L1+L2*L2)

(with or without ::)?

5 Dec 2014 10:26 #15200

If there is a problem with statement functions and so they were made obsolete, then why were contained functions introduced ? Surely the confusion about scope of variables in a statement function is very similar to that for a contained subroutine of function.

5 Dec 2014 10:50 #15201

Internal functions are more flexible because:

They can span more than 1 line. They can be recursive Variables in the host can be accessed. From Fortran 2008 they can be passed as arguments to subprograms.

5 Dec 2014 11:31 #15202

Quoted from LitusSaxonicum Would that be

DOUBLE PRECISION HP
HP(L1,L2) = DSQRT(L1*L1+L2*L2)

or

DOUBLE PRECISION HP(L1,L2) = DSQRT(L1*L1+L2*L2)

(with or without ::)?

The former will do. The latter will fail. Clive Page has a nice section on statement functions at http://www.star.le.ac.uk/~cgp/prof77.html#tth_sEc9.2 .

6 Dec 2014 12:56 #15203

Thanks for that. Not that it applies to me of course, because in my religion, non-implicit types are the work of the devil. I may, of course, be the only surviving member of the Original and True Church of the sainted John Backus!

Other devilry forbidden to congregants of this Church (if I am not the only one) includes using variables from the host and using internal functions of multiline length (continuation lines don't count in this). And as for passing function names as parameters, all I can say is Get thee behind me Fortran2008, thou art an offence to mine eye etc etc.

Seriously, if you can't understand a one-liner statement function, how the heck are you ever going to get your head round the new stuff? Metcalfe said somewhere that Fortran 8X (90 to you and me) was to simplify the syntax. Ha Ha - comedian.

It seems to me that a large proportion of the changes post Fortran 77 (but not all) appear to me to be simply alternative ways of doing something that you could already do - and could do perfectly with Algol 60 a half century ago (but only on a handful of computers). A pig with lipstick is still a pig. A standardised graphics system and an improvement on i/o would have been far more useful ... something like Clearwin+.

A little tip that helps one understand that something is a function is to put that hint into the function name, as in HP_FN or if one wants to make statement functions clearer, HP_SFN (or whatever grabs you). And there are also comments, whether or not you prefer them to begin with C or !

Eddie

8 Dec 2014 9:22 #15204

I have been using a small group of single line statement functions (both with and without IMPLICIT NONE) for 45 years with no problems at all.

9 Dec 2014 1:54 #15205

Eddie, You are not alone. The use of 'Implicit None' is offensive why not use it, because then, everyone knows what a variable or function starting with I,J,K,L,M,N is integer, etc. and the statement 'Implicit Real*8 (A-H,O-Z)' is also very good. 'Implict's sof character, logical and complex etc are all easily understood. Perhaps St. Bede was a member of the St. Backus Church School teaching staff, he was mates with Jock Kirk and Jake Harrison!. (I'm sure you will get the meaning of that comment.)

But..... I thought that it has allways been possible to pass function names as parameters in subroutine calls as long as you declared it external in the appropriate places. 'A long long time ago I can still remember' doing this in FTN77/386. Or perhaps I can't!

I feel old!

Ian

10 Dec 2014 6:27 #15207

Ian,

I'm having problems understanding your post, all except the last bit (I think).

In the beginning, the only names that had global scope were explicit FUNCTIONs and SUBROUTINEs, plus standard subprograms of either type (I include compiler extensions in that). All other names were local to the subprogram in which they were defined, although if given the same names in several routines it looked like they were more extensively available.

As far as I know, a statement function couldn't be used as a parameter with an EXTERNAL definition, but maybe I'm wrong. You could always use a formal FUNCTION in this way. Does it work if the subprogram which receives the name is expecting something of a different type?

Anyway, the traditional scoping rules are simple: they get more ever more complex in Fortran 90 et seq.

In Algol, the scoping rules were different, but simpler, so if we had:

begin; entier a; a:=3; begin; entier b b:=a*a; end; end;

(entier is the same as INTEGER), then anything defined in an outer 'begin ... end block' (such as a) is available in an inner block. Indenting was de rigeur to understand anything, and with the passage of time I've forgotten the correct usage for ; and for the equivalents to functions, sorry.

AS long as the rules are understood, it doesn't matter what they are, but it is obvious to me at least that if you have made the rules more complex you haven't made them simpler to understand!

Eddie

Please login to reply.