Can we indeed avoid goto in all cases? - fortran

Fortran 90 and later strongly recommend not to use goto statement.
However, I still feel forced to use it in either of the two cases:
Case 1 -- Instruct to re-enter the input value, e.g.
program reenter
10 print*,'Enter a positive number'
read*, n
if (n < 0) then
print*,'The number is negative!'
goto 10
end if
print*,'Root of the given number',sqrt(float(n))
stop
end program reenter
Case 2 -- To comment a large continuous part of a program (an equivalent to /* ... */ in C).
Eg.
print*,'This is to printed'
goto 50
print*,'Blah'
print*,'Blah Blah'
print*,'Blah Blah Blah'
50 continue
print*,'Blahs not printed'
How can I get rid of using goto statement and use some alternatives in the above two cases in Fortran 90?

Case 1
What you have is an indefinite loop, looping until a condition is met.
do
read *, n
if (n.ge.0) exit
print *, 'The number is negative!'
end do
! Here n is not negative.
Or one could use a do while lump.
Case 2
A non-Fortran answer is: use your editor/IDE's block comment tool to do this.
In Fortran, such flow control can be
if (i_dont_want_to_skip) then
! Lots of printing
end if
or (which isn't Fortran 90)
printing_block: block
if (i_do_want_to_skip) exit printing_block
! Lots of printing
end block printing_block
But that isn't to say that all gotos should be avoided, even when many/all can be.

depending on what you mean by "continuous part of a program" case 2 could be jumping out of some block structure, eg:
do i = 1,n
...
goto 1
...
enddo
...
1 continue
If you encounter such thing it can be quite a challenge to unravel the code logic and replace with modern structured coding. All the more reason not to "comment" that way..

Related

Fortran Basic Conditional and Loop Code Errors

I'm doing a very basic Fortran tutorial to learn it for grad school and I input the codes for conditionals and loops exactly as they were written in the tutorial but I keep getting the "unexpected end of file" error when I try to compile with gfortran.
This is my conditional code:
if (angle < 90.0) then
print *, 'Angle is acute'
else if (angle < 180.0) then
print *, 'Angle is obtuse'
else
print *, 'Angle is reflex'
end if
This is my loop code:
integer :: i
do i=1,10,2
print *, i ! print odd numbers
end do
Both of them are completed with end statements, so I'm not sure what else it wants. I've only just started teaching myself today, so I'm still just copying codes verbatim from the tutorial and not sure how to troubleshoot anything.
In the tutorial you are following the pieces of code shown are not complete programs. They cannot be compiled as they are.
You will see this frequently, especially in answers on this site.
The code fragments shown miss a lot of context to make clear the parts that are to be taught. That's perhaps a little unfortunate, but Fortran is quite a verbose language, and so there's a trade-off for clarity.
For a complete program you've possibly seen that "all programs must have an end statement to complete them". You may think that the end if and end do statements are suitable for this. They are not: you need an end program statement. The following are two minimal programs:
end
and
end program
(There are also forms with a program statement.)
That is:
if (.true.) then
print *, "Hello, world!"
end if
end program
is compilable if and only if that last line exists.
Further, things like implicit none and variable declarations and definitions would be part of the implied context of example fragments.
If you are just learning and want to try code start with the following skeleton
program test
implicit none
<variable declarations>
<program code>
stop
contains
<function definitions>
end program
The above structure should be enough for most one use programs (write a program to do one thing). The stop above isn't required, it just makes it clear to see where the program instructions actually end.
If you want to use standard numeric types include the iso_fortran_env before the implicit none statement
program test
use, intrinsic :: iso_fortran_env
implicit none
the above will allow you to define integer(int32), integer(int64), real(real32), real(real64), etc.

How to avoid repeated checking of an if-statement when the condition to be checked is deallocated within the if-block?

I have a fortran code using a derived type as follows:
if(type%value(1).LT.0D0 OR type%value(1).GT.1D0) then
if(type%value(1).LT.0D0) then
do something
end if
deallocate(type%value)
end if
In this scenario the statement type%value(1).LT.0D0 is checked twice. Is there a way to avoid this? More generally, is there a better approach to validate this?
Well, you have three paths:
type % value(1) < 0
type % value(1) > 1
0 <= type % value(1) <= 1
In all three paths the statements will be different, so you need two if statements.
Do something then deallocate
Only deallocate
Nothing
How you branch between the three paths is up to you, and the specifics of your code. The way you describe above is totally reasonable. If the evaluation is more computational intensive than a simple floating point comparison, it might be useful to store the results of this comparison in a logical variable, but other than that, it's fine.
Other ways are:
if (type % value(1) .LT. 0D0) then
do something
deallocate(type % value)
elseif (type % value(1) .GT. 1D0) then
deallocate(type % value)
end if
In a sense, this repeats the deallocate statement, but it distinguishes the paths better. I'm testing this out, I don't know the exact Fortran Standard, but my understanding is that if the value is less than 0, then it is deallocated, but the elseif isn't even tested, so it doesn't matter that it's no longer allocated at that point.
Ultimately, your method is fine. Make sure that the code is easy to read for you or whoever has to read the code in the future. I don't see any performance reason to chose one over the other.

What's faster in terms of timing closure, multiple "ifs" or an "if-else"?

Let's say I have some logic dependent on three signals a, b, and c to assign a variable d.
If I know a and b and c are logically (as in I know they will be, the tool won't necessarily be able to figure that out) going to be mutually exclusive, what would be faster in terms of the synthesized result?
This:
always #(posedge clk) begin
if (a) begin
d <= foo;
end
if (b) begin
d <= bar;
end
if (c) begin
d <= fizz;
end
end
Or this:
always #(posedge clk) begin
if (c) begin
d <= fizz;
end else if (b) begin
d <= bar;
end else if (a) begin
d <= foo;
end
end
I would think the former because there's less nesting, as in there's no check this, then check this, then check this. But I'd say the latter because if one conditional evaluates first, it doesn't need to consider the results of the other conditions. But maybe I'm mistaken and missing something.
Thank you in advance!
Most synthesis tools would likely create the same logic for both based on how you have structured it with the first case being a->b->c and the second being c->b->a with regards to conditional checks.
With that said...
Whoever needs to look at this would potentially not know about the exclusivity of the logic, leading them to control it wrong potentially if those conditional checks are controlled through some external signals. It's also hard to read from the standpoint of needing to really examine the code. An if/else clearly distinguishes "if this, else do this" and there is no ambiguity with regards to the outcome. I had to look at the order of the if's in the first structure before I saw what you were doing and how it matched.
Since we are talking about speed of logic, we can also discuss simulator speed. On your first structure, you are now causing the simulator do 3 if checks. The 2nd could be as low as 1 and high as 3. While you wouldn't see this impact performance if you have a smaller sim, if this was some logic that is instantiated many times on a fast clock, it would start to eat up sim cycles.
Both pieces of code will result in a priority mux. The only difference being, the order of the priority is decided by you/synthesis tool in the second/first pieces of code respectively.
However if you are targeting this code for an FPGA, you can embed the mutually exclusive part into the code with something like this
always#(*)
begin
case ( {a,b,c} )
3'b000: d_in <= d;
3'b001: d_in <= foo;
3'b010: d_in <= bar;
3'b100: d_in <= fizz;
endcase
end
always#(posedge clk)
begin
d<=d_in;
end
Regards,
Bharadwaj

How to read a list of integers from an input line

Is it possible to read a line with numerous numbers(integers) using Fortran?
lets say i have a file with only only line
1 2 3
the following program reads 3 integers in a line
program reading
implicit none
integer:: dump1,dump2,dump3
read(21,*) dump1,dump2,dump3
end
so dump1=1 dump2=3 dump3=3
If i have a file with only one line but with numerous integers like
1 2 3 4 5 6 7 8 ... 10000
is ti possible the above program to work without defining 10000 variables?
EDIT The first paragraph of this answer might seem rather strange as OP has modified the question.
Your use of the term string initially confused me, and I suspect that it may have confused you too. It's not incorrect to think of any characters in a file, or typed at a command-line as a string, but when all those characters are digits (interspersed with spaces) it is more useful to think of them as integers. The Fortran run-time system will
take care of translating a string of digit characters into an integer.
In that light I think your question might be better expressed as How to read a list of integers from an input line ? Here's one way:
Define an array. Here I define an array of fixed size:
integer, dimension(10**4) :: dump
(I often use expressions such as 10**4 to avoid having to count 0s carefully). This step, defining an array to capture all the values, seems to be the one you are missing.
To read those values from the terminal, at run-time, you might write
write(*,*) 'Enter ', 10**4, 'numbers now'
read(*,*) dump
and this will set dump(1) to the first number you type, dump(2) to the second, all the way to the 10**4-th. Needless to say, typing that number of numbers at the terminal is not recommended and a better approach would be to read them from a file. Which takes you back to your
read(21,*) dump
It wouldn't surprise me to find that your system imposes some limit on the length of a single line so you might have to be more sophisticated when trying to read as many as 10**4 integers, such as reading them in lines of 100 at a time, something like that. That's easy
read(*,*) dump(1:100)
will read 100 integers into the first 100 elements of the array. Write a loop to read 100 lines of 100 integers each.

In fortran, can I type function?

I want make a function as I type and read it as a function. For example, if I type x+y, then f(x,y)=x+y. Is this possible? The following code does not work.
real function f(x,y)
real x,y
write(6,*) "type f(x,y)"
read*, f
return
end
Yes, you can, but your syntax is a bit off.
PROGRAM READFUNC
REAL x,y,F,res
res = F(x,y)
WRITE(*,*) res
END
REAL FUNCTION F(x,y)
REAL x,y
WRITE (*,*) "Type in"
READ (*,*) F
RETURN
END
note that I compiled this w/ gfortran so I'm not sure if it uses any F90+ extensions or not.
EDIT After reading your edits, I see that this isn't what you want; you want some kind of eval/parser. In general this is not a trivial thing. You're going to have to do some kind of token parsing work.
However there are libraries that can do this for you that are already written.
See this article for an example of where to look for more research.
F(X,Y)=X+Y
99 READ(*,*)X,Y
WRITE(*,*)F(X,Y)
GO TO 99
You enter 3 4 or 3,4 and you get out 7