I am working with an old fortran77 script where a variable starting with the letter 'I' (indicating it is an integer) is used in a IF-statement, like
IF(I.EQ.1) CALL FUNC
without first being declared and a value being passed to it. So my question is what value does an undeclared integer get? The most logical seem to be 0 or 1. Thanks in advice!
Okay so this is pretty much how the routine works:
100 DO 10 J=1,20
doing stuff
IF (I.EQ.1) CALL FUNC
10 CONTINUE
200 DO 20 J=1,30
doing other stuff
IF (X.GT.0) Y = 1
20 CONTINUE
IF (Y.GT.0) GOTO 100
I = 1
GOTO 100
And as you can see the I is first defined after the two DO-loops. So how does this work the first time when the DO-loop 10 is executed.
Related
Here's what I'm trying to run:
if (z.le.zstart) then
if (y.ge.((6.95*wg_y2)/5)).and.(y.le.((12.55*wg_y2)/5)) then
indexmedia=nd
end if
end if
For context,
zstart is an arbitrary line of constant y.
wg_y2 = 5e-6
And for some reason it doesn't like the (y.ge.((6.95*wg_y2)/5)) bit, as the (1) was placed at the end of that bit.
I had a suspicion that it doesn't like anything that isn't an integer in the if statement but I changed 6.95 to 7 and 12.55 to 13 and it still didn't like it. Perhaps it needs to end up resolving to an integer?
I need these parameters to end up to
6.95 < y < 12.55 though.
Is there a workaround for this?
When compiling the code (not nice as I didn't declare the variables!, but that isn't the problem here so I abstain from it to keep it a bit small):
program tst
if (z.le.zstart) then
if (y.ge.((6.95*wg_y2)/5)).and.(y.le.((12.55*wg_y2)/5)) then
indexmedia=nd
end if
end if
end
one gets the error:
aa.f90:3:29:
if (y.ge.((6.95*wg_y2)/5)).and.(y.le.((12.55*wg_y2)/5)) then
1
Error: Cannot assign to a named constant at (1)
aa.f90:6:3:
end if
1
Error: Expecting END PROGRAM statement at (1)
This is due to a missing pair of round brackets in the line:
if (y.ge.((6.95*wg_y2)/5)).and.(y.le.((12.55*wg_y2)/5)) then
which should read
if ((y.ge.((6.95*wg_y2)/5)).and.(y.le.((12.55*wg_y2)/5))) then
This question already has an answer here:
How to avoid declaring and setting the value of a variable in each subroutine?
(1 answer)
Closed 5 years ago.
I have a program that calls functions within the same program but I want to declare and initialize the variables on the top and access them at the end of the program.
!Declaration
INTEGER TOPCHORD,BOTCHORD, SUPPS, PURLINS;
!Initialization
! Define Layers for connecting lines
TOPCHORD = 32
BOTCHORD = 32
SUPPS = 36
PURLINS = 30
INTEGER FUNCTION IFLANGE1(IEND1,IEND2,ISUP)
IFLANGE1=TOPCHORD
SELECT CASE(IEND1)
CASE(2,4,6,8,9,10)
IFLANGE1=BOTCHORD
IF(ISUP.EQ.1)IFLANGE1=SUPPS
END SELECT
SELECT CASE(IEND2)
CASE(2,4,6,8,9,10)
IFLANGE1=BOTCHORD
IF(ISUP.EQ.1)IFLANGE1=SUPPS
END SELECT
RETURN
END
I get error that variable 'SUPPS' referenced but not set
You might want to have a look at the documentation - you're missing a couple of important statements. (Also try to always include implicit none -- this is very helpful for catching certain issues).
A slightly modified code that should compile is
!Declaration
INTEGER TOPCHORD,BOTCHORD, SUPPS, PURLINS;
!Initialization
! Define Layers for connecting lines
TOPCHORD = 32
BOTCHORD = 32
SUPPS = 36
PURLINS = 30
contains !Indicate that the program unit contains other procedures
INTEGER FUNCTION IFLANGE1(IEND1,IEND2,ISUP)
IFLANGE1=TOPCHORD
SELECT CASE(IEND1)
CASE(2,4,6,8,9,10)
IFLANGE1=BOTCHORD
IF(ISUP.EQ.1)IFLANGE1=SUPPS
END SELECT
SELECT CASE(IEND2)
CASE(2,4,6,8,9,10)
IFLANGE1=BOTCHORD
IF(ISUP.EQ.1)IFLANGE1=SUPPS
END SELECT
RETURN
END FUNCTION !End the function definition
END !This is a required end statement to say we've reached the end of the program
This isn't the nicest style etc. but has the minimum number of changes to compile.
For any slightly more complex program I would strongly recommend using modules for storing variables (and also procedures) that you want to access from different parts of the code.
I am trying to convert a Rainflow cycle counting algorithm which is in Fortran, which is a language I am not familiar with, into Matlab.
There is a ready made Rainflow I've downloaded for Matlab but that does not fit the requirements of my project so I'm trying to build one from scratch.
Here is the Fortran code:
INTEGER BUFFER (4096), INDEX, VALUE, RANGE, MEAN, X, Y
INDEX = 0
10 CONTINUE
call 'get next peak/valley', VALUE
INDEX = INDEX + 1
BUFFER (INDEX) = VALUE
20 CONTINUE
IF (INDEX.LT.3) THEN
not enough points to form a cycle
GOTO 10
ELSE
X = ABS (BUFFER(INDEX) - BUFFER(INDEX - 1))
Y = ABS (BUFFER(INDEX - 1) - BUFFER(INDEX - 2))
IF (X.GE.Y) THEN
c -- cycle has been closed
RANGE = Y
MEAN = (BUFFER(INDEX-1) + BUFFER(INDEX-2))/2
c -- remove the cycle
INDEX = INDEX - 2
BUFFER(INDEX) = BUFFER(INDEX+2)
c -- see if this value closes any more cycles
GOTO 20
ELSE
GOTO 10
END IF
END IF
I had downloaded f2matlab (a Fortran to Matlab converter) but it requires a Fortran compiler which I do not have.
The bits I don't really understand how I can convert are:
The call 'get next… line (is this an input()?)
The BUFFER(4096) etc (is this a bit large to be a matrix in matlab?)
The GOTO/CONTINUE structure.
What do they mean, in English (or Matlab)?
I have seen
How to translate fortran goto state to matlab
and
translating loop from Fortran to MATLAB
but they do not help me very much.
This
call 'get next peak/valley', VALUE
isn't (currently) syntactically valid Fortran and I'm not sure whether any compiler of yore would have understood it either. I guess that it means get a VALUE for use in the following bits of code.
INTEGER BUFFER (4096)
is a simple declaration that BUFFER is a vector of 4096 integers, nothing to scare Matlab in that volume of data.
Finally, GOTO is an unconditional jump and the number following it is the label of the line to jump to, so GOTO 10 means execute the line with label 10 next. It was fairly common in FORTRAN of the vintage you are showing us to jump to a CONTINUE statement which is, in this context, a no-operation, execution continues to the next line.
In another context, with DO loops CONTINUE would have marked the end of the block of code inside the scope of the loop and would have a subtly different effect.
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.
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