I have a huge piece of Fortran code and I want to compile that code with gfortran. I have not worked with Fortran before. I do not know exactly what specification the code is of, but I found out that it can be compiled with at least Compaq Visual Fortran 6.6 - so I may guess it was written under it.
The general question is: Is there any automatic Compaq Visual Fortran to gfortran translator? I have found none.
In fact, the code does compile with gfortran after some fixes, but misbehaves at runtime: it does not read input files as expected. Here is an example of code:
CHARACTER*6 VAR1
CHARACTER*1 VAR2
CHARACTER*3 VAR3
OPEN (UNIT=CHANNEL, FILE=FILENAME, STATUS='OLD')
READ(CHANNEL, 38)VAR1,VAR2,VAR3
38 FORMAT(15X,A6,7X,A1,14X,A3)
And an example of data:
123456789012345------'1234567-'''''12345678901234---
.ABCDEF.GHI.JKLMNOPQR.STUVWX.YZABC.DEF.GHI.JKLM....P
123456789012345------1234567-12345678901234---
First line is how original app reads it, third - gfortran, second - an example of line from datafile (1-9 for ommited chars, - for read, ' for unmentioned by format, . in the example instead of spaces in the original line).
So, the results would be:
Origanal: VAR1 == 'MNOPQR', VAR2 == 'Y', VAR3 == '..P' - correct
gfortran: VAR1 == 'MNOPQR', VAR2 == '.', VAR3 == 'JKL' - wrong
gfortran is quite straightforward: it jumps over 15 characters, reads 6, jumps over 7 and so on. But the original application goes another way and I can not guess its logic. It still reads the specified number of chars, but jumps farther than specified. And it does read what it is expected to read.
I tried to specify exact lengths as they appear in the input file (15X,A6,8X,A1,19X,A3), and it works for gfortran, but it is not a long-term solution.
So, my more specific question is: Are there any differences in FORMAT statement in gfortran and Compaq Visual Fortran 6.6? (maybe, I am wrong thinking FORMAT is the cause)
UPD
I guess, there can be something with splitting into words or so. I mean gfortran just counts characters, but CVF does something different.
If this was a paper exercise and I was asked what the values of VAR1, VAR2 and VAR3 would be, I'd give the same result as gfortran.
What you are saying is really strange. I've just tried it on PowerStation4, IVF7 (the versions before and after CVF6.6) and they all give the same result as gfortran. I've also tried it with different word alignment, and different datatypes (not legal with gfortran but you can do that on the older compilers) and it comes up with the same answer.
Are you sure it is reading the file you think it is reading. powerstation and some versions of cvf have the 8.3 filename problem. They could not cope with long filenames.
Related
I have little knowledge of the Fortran language. I have come across some programs written in the 90s (see attached snapshot showing just a portion of a long script).
I'd like to know what kind of compiler is appropriate to execute such codes? I have installed gfortran-4.2.3 on my mac. I'm also not sure about the indentation in the attached code: if C (comment) is at column 1, does the main code start at column 9 or 7? what about the position of numbers placed in between referred by GO TO?
This is not Fortran 90. This is Fortran 77.
That said, gfortran is able to compile this code. Make sure that the file extension for the file is .f so that gfortran realises it's fixed-form.
The C needs to be in the first column, the numbers that you reference are labels, they can be between column 1 and 5. The asterisk at line 198 is a continuation character, meaning that this should be treated as part of the previous line. It must be in column 6. Everything else needs to be between columns 7 and 72 (inclusive)
Oh, and the 3-digit numbers at the very beginning are line numbers, and must not be in the source code.
Edited to add: Since you have to type it all again anyway, you might as well make it free-form:
Replace the C in the first column with !, and change the way continuation lines are marked: Turn this:
write (*, *) "This is some long text,
* which doesn't fit into a line"
Into this:
write(*, *) "This is some long text, " // &
"which doesn't fit into a line"
Everything else can stay like it is. (You can now use proper indentation, too!)
New Edit
So you've pasted the code that you wrote and the error messages, so I'm replying to that now.
In Fixed Form, any character past column 72 is ignored. You have a few lines with long strings, where the terminating quotation mark is in that ignored region.
Make sure that no line exceeds the 72nd row.
In a simple test routine i am curently writing in Fortran90, the string output is longer than the screen. When using the standard write(,) statement, the output in the Instead of simply add a new line and continue on the next line, a second newline is added before continuing the output.
Example code:
write(*,*) "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
Intel Visual Fortran Composer XE 2013 SP1 output:
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
Why that is ? Where does this extra newline come from ?
By using list-directed output, which you do with the second * in the arguments to the write statement, you surrender precise control of output formatting to the whims of the compiler writers. Seize back control with a specific format, something like write(*,'(a128)') (replacing 128 with whatever is appropriate for the length of string you want to write). See what happens then.
It might amuse you to learn to use the repeat function for, well, repetitive strings.
i'm totally new to Fortran, and i want to write a test program using a real*8 function called NeQuick, so i've written the following program :
program test
implicit real*8 (a-h,o-z)
aNe=NeQuick(400.0D0,45.0D0,15.0D0,10,1.929D2,15.0D0)
write(6,'(A,E12.5,A)')
& ' NeQuick electron density =',aNE,' m^-3'
call sleep(10)
end program
At the end when i compile it I have the following errors in each line of the little program : -Non-numeric character in statement label at 1 or
-Unclassifiable statement at 1
Can you guys please explain me what's wrong with my program ?
The way this code is written tells me that it was intended to be fixed-form source. This requires that all of the code start in column 7, except for the & in the second line of the WRITE statement which should be in column 6. Often when such code is pasted into an editor, the leading blanks are removed. If you do this, though, you will have to rename the source file to have a .f or .for file type so that the compiler knows it is fixed-form.
Another, perhaps easier solution is to put an & at the end of the first line of the WRITE - this will then make the source as you have it valid free-form.
For some perspective on this, please read Source Form Just Wants to be Free.
The program can run, I am not sure how to use open() and save the data in another external file name output.txt. My questions are stated below - please have a look and help.
program start
implicit none
integer ::n
real(kind=8)::x,h,k
real(kind=8),external:: taylorq
x=1.0
n=20
h=exp(x)
k=taylorq(x,n)
open(10,'output.txt') ----------- *question1:(when should i put this open file?)*
write(*,*)"The exact value=",h
write(*,*)"The approximate value=",k
write(*,*)"The error=",h-k
end program start
function taylorq(x,n)
implicit none
integer::n,i
real(kind=8):: x,taylor,taylor2,taylorq,h
h=exp(x)
taylor=1.
taylor2=taylor
write(*,*)"i exact appro error"-----------question2:(actually I want to draw a table with subtitle i, exact, appro, error in each column, is there a nice way to arrange them like eg.we can use %5s)
do i=1,n
taylor=taylor*x/i
taylor2=taylor2+taylor
write(10,*)i,h,taylor2,taylor2-h --------question3:*(I want to save the data written here into file output.txt)*
end do
close(10)
taylorq=taylor2
end function taylorq
1. where to open
You should put open(10,...) so it executes before any write(10,...) -- or read(10,...) if this was input.
Since your writes occur in the function taylorq, you should open() before the statement that calls taylorq.
For programs that do very large computations, which Fortran is suited/famous for, it is often best to do
all file open's very near the beginning of the program, so that if there is a problem opening any file,
it is caught and fixed without wasting hours or days of work. But your program is much simpler than that.
2. formatting
Yes, Fortran can do formatted output -- and also formatted input. Instead of a text string with
interpolated specifiers (like C and the C part of C++, and Java, and awk and perl and shell) it uses specifiers
with optionally interpolated text values, and the specifiers are written with the format letter on
the left followed by the width (almost always) and other parameters (sometimes).
You can either put the format directly in the WRITE (or READ) statement, or in a separate FORMAT
statement referred to by its label in the I/O statement.
write (10, '(I4,F10.2,F10.2,F10.2)' ) i,h,taylor2,taylor2-h
or
write (10, 900) i,h,taylor2,taylor2-h
! this next line can be anywhere in the same program-unit
900 format (I4,F10.2,F10.2,F10.2)
Unlike C-family languages, Fortran will always output the specified width; if the value doesn't fit,
it prints asterisks ***** instead of forcing the field wider (and thus misaligned) (or truncating as
COBOL does!). Your series grows fast enough you might want to use scientific notation like E10.3.
(The format letters can be in either case, but I find them easier to read in upper. YMMV.)
There are many, MANY, more options. Any textbook or your compiler manual should cover this.
I can't figure out what in the world this "9999" is doing in front of the e20.8, in the label of this fortran write statement.
Is does not refer to any other line in the code. In other words, there isn't a line labeled 9999 to which it refers, elsewhere in the program.
write(11,'(9999e20.8)') (9999.0, i=1,2*(numant+numunique))
I'm boggled - I haven't found the answer from google web searches, although I think I get the general picture about write statement syntax and formatting.
Is this enough info provided to make sense?
It's a repetition count; the general format for a format code is (count)(type)(format), eg as described in this tutorial here.
Unlike C-based languages, unused formatting codes are simply ignored, so this line essentially says "write out as many real numbers in scientific format (with 8 digits after the decimal) as there are in the following output list". (If you don't like doing it this way, with a hardcoded "big enough" number, you'd have to programatically generate the format string to have the "right" repetition code.
The output list is an implied-do loop, which generates the number 9999.0 2*(numant+numuniqe) times.