Fortran 66 if() go to - fortran

I'm trying to understand a code from a article that I have to read for a project I'm working for, and it's written Fortran 66.
I don't understand the way it will work. I tried to write a similar code with same structures but it doesn't work. It's something similar to this
if(conditional.1)go to 20
*some code*
go to 30
20 if (conditional.2)
*some code*
go to 30
30 continue
If the conditional.1 is True it will go to 20 or it will go to 30
And if it's false it will go to20?
It would be similar to this?:
if(conditional.1)then
*some code*
end if
if(conditional.2)then
*some code*
end if

This is an example of spaghetti code that you get from overusing GOTO and from the lack of better structures in FORTRAN 66. You can visualize the evolution using a flowchart.
If conditional 1 is .true. then you skip the first *some code*. So I believe it would be
if (.not. conditional.1) then
*some code 1*
else if (conditional.2) then
*some code 2*
end if
in Fortran 77 and later.

Related

unclassifiable statement at (1) Fortran Error

at line 64 confirmed as the errors began
I was asked to modify a legacy code. I have found these errors when compiling error compiling picture . Does anybody know how to solve these errors? I use gfortran as my compiler.
The source code:
* Spectral analysis of measured data *
PARAMETER (ND=86400,NSP=43200,NND=86400)
COMMON /WDATA/ WD(NND),WD2(NND)
COMMON /SPEC/ WSP(NSP)
COMMON /TSDATA/ TS(ND*2),CTTS(ND*2)
COMMON /SPDATA/ P(NSP),DF
REAL MEAN
DATA DT/1.0/
DATA COTL/14400.0/
DATA COTS/600.0/
PI=3.141593
OPEN(32,FILE="Pw.txt",STATUS="OLD")
OPEN(12,FILE="output1",STATUS="UNKNOWN")
OPEN(13,FILE="output2",STATUS="UNKNOWN")
DO J=1,NND
READ(32,*)WD(J)
END DO
TOTAL=0.0
MEAN=0.0
DO J=1,NND
TOTAL=TOTAL+WD(J)
END DO
MEAN=TOTAL/FLOAT(NND)
DO J=1,NND
WD(J)=WD(J)-MEAN
END DO
Numerical filtering and Spectral analysis
M=ND/2
KF=1
TD=DT*FLOAT(ND)
DF=1./TD
DO J=1,ND
TS(J)=WD(J)
TS(J+ND)=0.
END DO
COFL=1./COTL
COFH=1./COTS
NCUTL=IFIX((COFL+DF/2.)/DF)+1
NCUTH=IFIX((COFH-DF/2.)/DF)+1
=========================
CALL CUTOFF(M,NCUTL,NCUTH)
=========================
DO J=1,ND
WD2(J)=CTTS(J)
END DO
=================================
SUBROUTINE CUTOFF(M,NCUTL,NCUTH)
=================================
PARAMETER(ND=86400,NSP=43200)
COMMON /TSDATA/ TS(ND*2),CTTS(ND*2)
COMMON /FFTDATA/ W1(ND*2)
MM=M+M
M4=MM+MM
DO J=1,MM
W1(2*J-1)=TS(J)
W1(2*J)=TS(J+MM)
END DO
===============
CALL FOUR1(MM,1)
===============
DO J=1,M
IF(J.EQ.1.AND.NCUTL.GT.0)THEN
W1(1)=0.
W1(2)=0.
ELSE IF(J.LT.NCUTL)THEN
W1(2*J-1)=0.
W1(2*J)=0.
W1(M4-2*J+3)=0.
W1(M4-2*J+4)=0.
END IF
IF(J.GT.NCUTH)THEN
W1(2*J-1)=0.
W1(2*J)=0.
W1(M4-2*J+3)=0.
W1(M4-2*J+4)=0.
END IF
IF(NCUTH.GT.M) THEN
W1(MM+1)=0.
W1(MM+2)=0.
END IF
END DO
-----------------
CALL FOUR1(MM,-1)
-----------------
DO I=1,MM
CTTS(I)=W1(2*I-1)/FLOAT(MM)
CTTS(I+MM)=W1(2*I)/FLOAT(MM)
END DO
RETURN
END
==========================
SUBROUTINE FOUR1(NN,ISIGN)
==========================
PARAMETER(ND=86400)
REAL*8 WR,WI,WPR,WPI,WTEMP,THETA
COMMON /FFTDATA/ DATA(ND*2)C
N=2*NN
J=1
DO 11 I=1,N,2
IF(J.GT.I) THEN
TEMPR=DATA(J)
TEMPI=DATA(J+1)
DATA(J)=DATA(I)
DATA(J+1)=DATA(I+1)
DATA(I)=TEMPR
DATA(I+1)=TEMPI
ENDIF
M=N/2
1 IF ((M.GE.2).AND.(J.GT.M)) THEN
J=J-M
M=M/2
GO TO 1
ENDIF
J=J+M
11 CONTINUE
MMAX=2
2 IF (N.GT.MMAX) THEN
ISTEP=2*MMAX
THETA=6.28318530717959D0/(ISIGN*MMAX)
WPR=-2.D0*DSIN(0.5D0*THETA)**2
WPI=DSIN(THETA)
WR=1.D0
WI=0.D0
DO 13 M=1,MMAX,2
DO 12 I=M,N,ISTEP
J=I+MMAX
TEMPR=SNGL(WR)*DATA(J)-SNGL(WI)*DATA(J+1)
TEMPI=SNGL(WR)*DATA(J+1)+SNGL(WI)*DATA(J)
DATA(J)=DATA(I)-TEMPR
DATA(J+1)=DATA(I+1)-TEMPI
DATA(I)=DATA(I)+TEMPR
DATA(I+1)=DATA(I+1)+TEMPI
12 CONTINUE
WTEMP=WR
WR=WR*WPR-WI*WPI+WR
WI=WI*WPR+WTEMP*WPI+WI
13 CONTINUE
MMAX=ISTEP
GO TO 2
ENDIF
RETURN
END
You haven't closed the main program with an end statement before the subroutine cutoff statement
DO J=1,ND
WD2(J)=CTTS(J)
END DO
=================================
SUBROUTINE CUTOFF(M,NCUTL,NCUTH)
=================================
This should read something like
DO J=1,ND
WD2(J)=CTTS(J)
END DO
END
SUBROUTINE CUTOFF(M,NCUTL,NCUTH)
however that doesn't really make sense. I'm sure there are more missing lines. There are also many illegal statements in the code presented mostly due to bad formatting as Vladimir F has noted.
Muhajjir,
If gfortran is anything like fortran used to be, this code will generate a
plethora of errors. One thing is for sure, there does HAVE to be and END statment at the end of the main. Otherwise, the compiler gets VERY confused. In
addition, some of your statments appear to have code to the left of column 7.
Remember, fortran dates from the days of IBM punch cards, which were HIGHLY
column oriented. A capital 'c' was typically used, in column 1, to indicate a
comment. Column 6 was reserved for continuation character, which eventually
became any character you wanted, as long as column 6 was not empty. Numbers used as labels HAD to start in column 1 and could not go past column 5 into 6, or beyond. This code looks like many of these basic rules have been violated. Check everything, straighten it all out, and everythng should be fine. If not, we can go from there.
Blake Mitchell
Retired free lance programmer
P.S. To whom it may concern,
I have read through the how to answer link and this answer appears to fit the
requirements perfectly. Why do you think it doesn't?

Skipping a part of the code according to command line arguement

I recently wrote a FORTRAN code which includes a part where I have used bubble-sort algorithm. Now, it takes much time due to the sorting of a very large files(~7/8 mins). However, mostly input files are arranged in such a way that sorting could be skipped and save some time. For which GO TO and CONTINUE is my friend. But I don't exactly know where to put these construct.
variable declaration
!****************** Name of the *.inp file from command line *****************
numargs=iargc()
IF (numargs.eq.3) THEN
CALL getarg(1,inputfile)
WRITE(*,*) ' Input: ',trim(inputfile)
CALL getarg(2,outputfile)
WRITE(*,*) 'Output: ',trim(outputfile)
CALL getarg(3,carg)
WRITE(*,*) 'Sorting invoked...'
ELSE IF (numargs.eq.2) THEN
CALL getarg(1,inputfile)
WRITE(*,*) ' Input: ',trim(inputfile)
CALL getarg(2,outputfile)
WRITE(*,*) 'Output: ',trim(outputfile)
**maybe IF statement for skipping the sorting part using GO TO (how?? IDK.)**
ELSE
WRITE(*,*) '****** The input and output filenames are missing! ******'
CALL exit(0)
END IF
INQUIRE(file=inputfile,exist=lex)
IF(.not.lex) THEN
WRITE(*,*) '**** file ', trim(inputfile), ' Does not exist!'
CALL exit(-1)
ENDIF
INQUIRE(file=outputfile,exist=lex)
IF(lex) THEN
WRITE(*,*) '**** file ', trim(outputfile), ' exists!'
WRITE(*,*) 'Delete and run the program again'
CALL exit(-1)
ENDIF
**estimation of records in input file**
**reading input file**
**bubble sort** (to be skipped or not depending upon command line argument)
**some more computation**
END
I hope I was clear enough! looking forward to your suggestions and guidance.
PT
I wouldn't use goto. I'd rather do something akin to the following
Logical :: sort_needed
sort_needed = .True.
... skip first part ...
ELSE IF (numargs.eq.2) THEN
CALL getarg(1,inputfile)
WRITE(*,*) ' Input: ',trim(inputfile)
CALL getarg(2,outputfile)
WRITE(*,*) 'Output: ',trim(outputfile)
sort_needed = .False.
ELSE
WRITE(*,*) '****** The input and output filenames are missing! ******'
CALL exit(0)
END IF
... skip to sort ....
If( sort_needed ) Then
Call sort( appropriate_arguments )
End If
...
End
In general avoid goto, it tends to lead to confusing code. While I'm not a zealot in modern Fortran it's very rarely the best way - in fact I honestly can't remember the last time I used it in anger
A few other things
1) This one is easy enough to follow but get into the habit of posting complete code, rather than fragments. More often than not it clarifies what you are trying to ask.
2) Bubble sort is a horribly inefficient algorithm. At least use something like selection sort as long as the files are not to big. However it is likely that something like a good quick or heap sort will save you lots of time in the long run
3) Fortran has standard ways of accessing the command line, and iargc and getarg are NOT the way of doing it. I suggest you look up and use command_argument_count and get_command_argument, any good, up to date Fortran book will cover these

Debugging DO loop / IF blocks in a Fortran 90 program (Beginner level)

I would be grateful if someone could help me out here. I'm just starting out learning how to program, so there is a great chance I'm missing something very obvious. I'm trying to write a program in Fortran 90 that solves question 4 i) on page 45 of this pdf. I have finally managed to get my code to compile to something, but now that something is somewhat rubbish, the data it produces is crazy (as time increases, I get a decrease in distance after whatever I input at t0). Can someone spot my mistake? I realize this is quite a lot of code to look through, I'm sorry for asking so much of you. Thanks in advance for looking through!
PROGRAM PARACHUTIST
! Tabulation of parachutist's descent z and and speed zdot
! as functions of time t
!Assign the program's associated constants
IMPLICIT NONE
REAL z, zdot, g, U1, U2, z0, u0, t0, q0, t, x,c,s
INTEGER I
g=9.8
U1=54
U2=5
!Break z0 down a little with q0
q0=COSH(g*t0/U1)
z0=U1**2/g*LOG(q0)
u0=U1*TANH(g*t0/U1)
!Prompt for and read in the free-fall time
Print*, 'Input free-fall time in seconds:'
Read*, t0
!Print the table headings
WRITE(*,1000)
1000 FORMAT (6X, 'TIME', 6X, 'DISTANCE', 6X, 'VELOCITY', /6X, '(SEC)', 7X, '(M)', 10X, '(M/SEC)',&
/6X, '0.0', 10X, '0.0', 10X, '0.0' )
!Loop covering the specified times
t=0
DO I=0,20
! Calculate the distance above ground
200 IF(t<=t0) THEN
x=g*t/U1
z=U1**2/g*LOG(COSH(x))
zdot=U1*TANH(x)
Elseif(t>t0) THEN
x=g*(t-t0)/U2
!store re-used expressions
c=cosh(x)
s=sinh(x)
z= z0 + (U2**2/g)*LOG(c+ (u0/U2)*s)
zdot=U2*(U2*s+u0*c)/(U2*c+u0*s)
Endif
!Print a line of table using T formats
WRITE(*,100) t, z, zdot
100 Format(4X, F5.2, 6X, F7.2, 6X, F7.2)
!Stop with message if landed
If(z.GE.500) THEN
PRINT*, 'LANDED'
STOP
!If we haven't yet landed then increment t as in
! problem specs
Elseif(t<15) then
t=t+1
Elseif(t.GE.15) then
t=t+10
ENDIF
!End of the t-loop
END DO
END PROGRAM PARACHUTIST
I wrote this as two comments, but it was really too lengthy. Go ahead and delete it all if you had planned to do so. I just browsed through a document comparing Fortran77 and "modern" Fortran90. (I coded in Fortran77 when I was just starting school, awhile ago...). Here are some suggestions:
Be careful with your use of "ELSEIF". It is usually okay for ELSE and IF to have the space omitted, but that is not true otherwise with free-format code (I think the only other instances of space-optional are DOUBLE PRECISION, ELSE IF, GO TO, END DO, and END IF).
An advantage of using Fortran90 is that you shouldn't even need ELSE IF's, (nor computed GOTO's!) as there is SELECT CASE.
You shouldn't need FORMAT either, as it can be incorporated directly with a format string in the READ or WRITE statement itself.
Yes, you can use either the old Fortran 77 operators .GE..GT..EQ..NE..LE..LT. or the new ones >= > == /= <= <. However, I'm not sure if you should mix them, which I noticed in your code.
EDIT: The second link above, about Control Structures, describes how you can use DO loops instead of IF's in Fortran90, sections 3.2 - 3.5. You can use named DO's, indefinite DO loops, DO WHILE's, all sorts of things! There are examples too. (The name of the entire document is Fortran90 for Fortran77 Programmers.)

problem using formatted Fortran `write(6,*)` output

I'm currently porting an application from Fortran to C and need to output some variables to compare results. I'm very new to Fortran, and although i understand the code and have now ported several thousand lines, I'm a noob at writing Fortran code myself.
This code:
write(6,'(A,I3,A,E12.8,A,E12.8,A,E12.8,A,E12.8,A,E12.8)') 'iHyd:',
& ih,'; dzdr: ',dzdr,'; tauray:', tauRay,'; zRay: ',
& zray,'; ampRay: ',realpart(aray),'+j*',
& imagpart(aray),'; qRay: ',qray,'; width :',w
Compiles fine, but when run, the program exits with:
At line 296 of file calcpr.for (unit = 6, file = 'stdout')
Fortran runtime error: Expected INTEGER for item 15 in formatted transfer, got REAL
(A,I3,A,E12.8,A,E12.8,A,E12.8,A,E12.8,A,E12.8)
^
q0: 1432.3944878270595
nArrayR: 501 nArrayZ: 201
iHyd: 1; dzdr: ************; tauray:************; zRay: ************; ampRay: NaN+j* NaN
; qRay:
Besides being really ugly, it doesn't make much sense to me, as ìh is declared as integer*8 and not as real.
So how can i solve this?
I'm counting 6 character&variable specifications in the format statement, but you're printing 8 of them.
edit:
a nicer use of the format statement would be '(A,I3,7(A,E12.8))'
Fortran "recycles" the format if there are more things to be printed than specified in the format statement. If a write statement gives results you don't understand, to diagonose the problem it may be helpful to remove the things printed one at a time until the error goes away.
It says "item 15", which I would take to be down near the end of your list, not ih at the beginning. It's clear that both "w" and "qray" are being printed as REAL; is either one of them an INTEGER? You may need to change the format specifier then.

Syntactical analysis with Flex/Bison part 2

Hallo,
I need help in Lex/Yacc Programming. I wrote a compiler for a syntactical analysis for inputs of many statements. Now i have a special problem.
In case of an Input the compiler gives the right output, which statement is uses, constant operator or a jmp instructor to which label, now i have to write so, if now a if statement comes, first the first command (before the else) must be give out when the assignment of the if is yes then it must jump to the end because the command after the else isnt needed, so after this jmp then the second command must be give out. I show it in an example maybe you understand what i mean.
Input adr. Output
if(x==0) 10 if(x==0)
Wait 5 20 WAIT 5
else 30 JMP 50
Wait 1 40 WAIT 1
end 50 END
like so. I have an idea, maybe i can do it whith a special if statement like
IF exp jmp_stmt_end stmt_seq END
when the if statement is given in the input the compiler has to recognize the end ofthe statement and like my jmp_stmt in my compiler ( you have to download the files from http://bitbucket.org/matrix/changed-tiny) only to jump to the end. I hope you understand my problem.thanks.
I would do this by a two-stage output: the first pass wold generate a list with each output statement, where the jump targets are encoded by labels, and a second pass, where this list is used to generate the real output. Something like this:
pass one:
Number Label Satatement
10 if(x==0)
20 WAIT 5
30 JMP (A)
40 WAIT 1
50 A END