Excess of array dimension in Fortran 90/95 - fortran90

I am very curious about how printing of the 3rd row in the following is possible or at least why it is not a trash value:
PROGRAM b
INTEGER:: A(2,2) = reshape((/1,2,3,4/),(/2,2/))
PRINT*, A(1,:)
PRINT*, A(2,:)
PRINT*, A(3,:)
END PROGRAM b
My result is:
1 3
2 4
3 66825
I would really appreciate your help. Thanks in advance.

Your 66825 is a trash value! Even if you got just 0, it is still an undefined behavior that can cause bad result or crash your program (or even start WWIII). Do not do this. Use features provided by the compiler to check the array bounds and other similar stuff:
gfortran -fcheck=all
ifort -check
and so on.
You can also use valgrind on Linux to see undefined values and invalid reads and writes in memory.

Related

Swift LLDB is not changing values / has no effect

having a code like this:
var foo: Int = 0
print (foo)
With a breakpoint at the print line... then doing:
(lldb) exp foo = 7
(lldb) p foo
(Int) $R2 = 7
0
print(x) still returns 0 instead of 7. How is that possible?
More details would help, but in general, I have seen this happen in three cases:
1) When you have a let, the compiler is free to replace the let with its value. This is not your case, but for sake of argument, given:
let x = 0
print(x)
The compiler is free to rewrite this as
print(0)
leaving the let binding in only for the sake of the debugger. Now, a let is a let, so writing to it is not exactly a well-defined operation. With that said, C compilers seem to not take that same kind of approach with const values, so that failure mode might surprise somebody
2) If you call a function, the compiler is (essentially) going to emit code to push the arguments on the stack, and then jump to the code for the function. In theory, one would expect the line table in the debug info to guide the debugger to stop before the arguments are pushed. Then,
>> push x
call print
A write to x would actually "mean" something in the context of your print call. But, if the line tables actually make us stop at the call, even if you write to "x", it has already been pushed, and the old value will be used
3) The compiler might actually be using a copy of "foo" that is in a register, but for the sake of debug info, pointing us to a stack copy of "foo" which is actually never used, and only updated when writes to "foo" happen. If that is the case, LLDB will gladly write to the stack, but that won't affect the program's behavior as it is not actually reading from the stack
Fun things to try to figure this out include:
the LLDB disassemble command
(lldb) reg read pc
(lldb) dis -s <value of program counter>
or
(lldb) fr var -L foo
and then read at the memory address (or the register) that LLDB gives out as the location of "foo"
or
in your app, print(x) twice, and see if the second print shows a different value

open statement in a recursive subroutine

I wanted to write my results into a file which is produced in a recursive subroutine. And I also wanted to assign the data(read) in the file to an array in my main program in fortran90.
program permutations
implicit none
call generate (position_min)
open(unit=20, file="a.dat", status="old")
do i=1,720
read(20,*)(G(i,j),j=1,6)
end do
contains
recursive subroutine generate (position)
implicit none
integer, intent (in) :: position
integer :: value
if (position > position_max) then
open(unit=20, file="a.dat", status="unknown")
write (20, *) permutation
else
call generate(position+1)
end if
end subroutine generate
end program permutations
This program gives me the following runtime error.
At line 19 of file p2.f90 (unit = 20, file = 'a.dat')
Fortran runtime error: End of file
How do I fix this?
I think the answer is primarily my comment to the question. If you look at your code (neglecting the undeclared variable issue), in particular the if-statement of the recursive subroutine, you should note that you have
if (position > position_max) then
open(unit=20, file="a.dat", status="unknown")
write (20, *) permutation
else
call generate(position+1)
end if
that is, you are only writing to file if position > position_max. Satisfying this condition writes one line to a.dat and then completes all of the previous if statements. What you probably meant to have was it writing to file each time through the recursive loop; to do that, you would want something like
open(20,file="a.dat",status="unknown")
write(20,*) permutation
close(20)
if(position > position_max) then
return
else
call generate(position+1)
endif
In running this, I found I was getting 2 extra lines (due to writing at position=position_min and at position=position_max). You probably could tweak that to get exactly 720, but I think that this part is irrelevant because you can change your read loop to the following
i=1
do
read(20,*,iostat=ierr) G(i,:)
if(ierr/=0) exit
i = i+1
enddo
A normal read returns an iostat of 0 and an end-of-file returns -1, so as long as you can read you will continue the loop and break when the EOF is found.
After fixing up the undeclared variables, adding the close(20) statement, and adjusting as I commented above, I had no problems writing and reading in the recursive subroutine.

Read integer statement

I am quite new with fortran and have a question. I need to read 2 integers from the following line:
K=234, L=241, I=0
I am not interested in the last value. Just need the integers 234 and 241. I tried it with
read(20,'(3X,I3,3X,I3)')a,b
It compiles, but when I run the program I always get the error message:
At line 27 of file test.f90 (unit = 20, file = 'int_p2.dat')
Fortran runtime error: Bad value during integer read
Don't know what I am doing wrong. Can someone give me some advice?
You have strings in your line, so your READ statement ought to account for it. You should replace it with
READ(20, '(3(a2,i3,2x))') dumChar, k, dumChar, l, dumInt, dumChar
where dumChar is a character of length 2 and dumInt is an integer.
I don't see a problem in your code. (off course, your format is wrong, but should not give runtime error). Also, you are escaping chars (K,L) rather then reading them. compiler should not complain. but 3X will eat up 1 integer for K=234
Program se
Implicit None
integer :: K,L,I,a,b
open(20, file="se.in",status='old')
read(20,'(3X,I3,3X,I3)')a,b
close(20)
write(*,*)a,b
End Program se
$ cat se.in
K=234, L=241, I=0
$gfortran se.f90
$ ./a.out
34 241
If you still getting the problem, and if this are one single line you are trying to read, do
remove any space before K= in the file.
I think this is the error, as the code is reading non-integer.

How to use command line arguments in Fortran?

GCC version 4.6
The Problem: To find a way to feed in parameters to the executable, say a.out, from the command line - more specifically feed in an array of double precision numbers.
Attempt: Using the READ(*,*) command, which is older in the standard:
Program test.f -
PROGRAM MAIN
REAL(8) :: A,B
READ(*,*) A,B
PRINT*, A+B, COMMAND_ARGUMENT_COUNT()
END PROGRAM MAIN
The execution -
$ gfortran test.f
$ ./a.out 3.D0 1.D0
This did not work. On a bit of soul-searching, found that
$./a.out
3.d0,1.d0
4.0000000000000000 0
does work, but the second line is an input prompt, and the objective of getting this done in one-line is not achieved. Also the COMMAND_ARGUMENT_COUNT() shows that the numbers fed into the input prompt don't really count as 'command line arguments', unlike PERL.
If you want to get the arguments fed to your program on the command line, use the (since Fortran 2003) standard intrinsic subroutine GET_COMMAND_ARGUMENT. Something like this might work
PROGRAM MAIN
REAL(8) :: A,B
integer :: num_args, ix
character(len=12), dimension(:), allocatable :: args
num_args = command_argument_count()
allocate(args(num_args)) ! I've omitted checking the return status of the allocation
do ix = 1, num_args
call get_command_argument(ix,args(ix))
! now parse the argument as you wish
end do
PRINT*, A+B, COMMAND_ARGUMENT_COUNT()
END PROGRAM MAIN
Note:
The second argument to the subroutine get_command_argument is a character variable which you'll have to parse to turn into a real (or whatever). Note also that I've allowed only 12 characters in each element of the args array, you may want to fiddle around with that.
As you've already figured out read isn't used for reading command line arguments in Fortran programs.
Since you want to read an array of real numbers, you might be better off using the approach you've already figured out, that is reading them from the terminal after the program has started, it's up to you.
The easiest way is to use a library. There is FLAP or f90getopt available. Both are open source and licensed under free licenses.
The latter is written by Mark Gates and me, just one module and can be learned in minutes but contains all what is needed to parse GNU- and POSIX-like command-line options. The first is more sophisticated and can be used even in closed-source projects. Check them out.
Furthermore libraries at https://fortranwiki.org/fortran/show/Command-line+arguments
What READ (*,*) does is that it reads from the standard input. For example, the characters entered using the keyboard.
As the question shows COMMAND_ARGUMENT_COUNT() can be used to get the number of the command line arguments.
The accepted answer by High Performance Mark show how to retrieve the individual command line arguments separated by blanks as individual character strings using GET_COMMAND_ARGUMENT(). One can also get the whole command line using GET_COMMAND(). One then has to somehow parse that character-based information into the data in your program.
I very simple cases you just need the program requires, for example, two numbers, so you read one number from arg 1 and another form arg 2. That is simple. Or you can read a triplet of numbers from a single argument if they are comma-separated like 1,2,3 using a simple read(arg,*) nums(1:3).
For general complicated command line parsing one uses libraries such as those mentioned in the answer by Hani. You have set them up so that the library knows the expected syntax of the command line arguments and the data it should fill with the values.
There is a middle ground, that is still relatively simple, but one already have multiple arguments, that correspond to Fortran variables in the program, that may or may not be present. In that case one can use the namelist for the syntax and for the parsing.
Here is an example, the man point is the namelist /cmd/ name, point, flag:
implicit none
real :: point(3)
logical :: flag
character(256) :: name
character(1024) :: command_line
call read_command_line
call parse_command_line
print *, point
print *, "'",trim(name),"'"
print *, flag
contains
subroutine read_command_line
integer :: exenamelength
integer :: io, io2
command_line = ""
call get_command(command = command_line,status = io)
if (io==0) then
call get_command_argument(0,length = exenamelength,status = io2)
if (io2==0) then
command_line = "&cmd "//adjustl(trim(command_line(exenamelength+1:)))//" /"
else
command_line = "&cmd "//adjustl(trim(command_line))//" /"
end if
else
write(*,*) io,"Error getting command line."
end if
end subroutine
subroutine parse_command_line
character(256) :: msg
namelist /cmd/ name, point, flag
integer :: io
if (len_trim(command_line)>0) then
msg = ''
read(command_line,nml = cmd,iostat = io,iomsg = msg)
if (io/=0) then
error stop "Error parsing the command line or cmd.conf " // msg
end if
end if
end subroutine
end
Usage in bash:
> ./command flag=T name=\"data.txt\" point=1.0,2.0,3.0
1.00000000 2.00000000 3.00000000
'data.txt'
T
or
> ./command flag=T name='"data.txt"' point=1.0,2.0,3.0
1.00000000 2.00000000 3.00000000
'data.txt'
T
Escaping the quotes for the string is unfortunately necessary, because bash eats the first quotes.

Limiting the amount of information printed by Perl debugger

One of my pet peeves with debugging Perl code (in command line debbugger, perl -d) is the fact that mistakenly printing (via x command) the contents of a huge datastructure is guaranteed to freeze up your terminal for forever and a half while 100s of pages of data are printed. Epecially if that happens across slowish network.
As such, I'd like to be able to limit the amount of data that x prints.
I see two approaches - I'd be willing to try either if someone knows how to do.
Limit the amount of data any single command in debugger prints.
Better yet, somehow replace the built-in x command with a custom Perl method (which would calculate the "size" of the data structure, and refuse to print its contents without confirmation).
I'm specifically asking "how to replace x with custom code" - building a Good Enough "is the data structure too big" Perl method is something I can likely do on my own without too much effort although I see enough pitfalls preventing the "perfect" one from being a fairly frustrating endeavour. Heck, merely doing Data::Dumper->Dump and taking the length of the string might do the trick :)
Please note that I'm perfectly well aware of how to manually avoid the issue by recursively examining layers of datastructure (e.g. print the ref, print the count of keys/array elements, etc...)... the whole point is I want to be able to avoid thoughtlessly typing x $huge_pile_of_data without thinking - or stumbling on a bug populating said huge pile of data into what should be a scalar.
The x command takes an optional argument for the maximum depth to display. That's not quite the same as limiting the amount of data to N pages, but it's definitely useful to prevent overload.
DB<1> %h = (a => { b => { c => 1 } } )
DB<2> x %h
0 'a'
1 HASH(0x1d5ff44)
'b' => HASH(0x1d61424)
'c' => 1
DB<3> x 2 %h
0 'a'
1 HASH(0x1d5ff44)
'b' => HASH(0x1d61424)
You can specify the default depth to print via the o command, e.g.
DB<1>o dumpDepth=1
Add that to your .perldb file to apply it to all debugger sessions.
Otherwise, it looks like the x command invokes DB::dumpit() which is just a wrapper for dumpval.pl (or, more specifically, the main::dumpValue() sub it defines). You could modify/replace that script as you see fit. I'm not sure how you'd make it interactive, though.
The | command in the debugger pipes another command's output to your pager, e.g.
DB<1> |x %huge_datastructure