For Programmers: Free Programming Magazines  


Home > Archive > Fortran > August 2007 > Interpreting read statement in FORTRAN IV code









You are viewing an archived Text-only version of the thread. To view this thread in it's original format and/or if you want to reply to this thread please [click here]

 

Author Interpreting read statement in FORTRAN IV code
ssragunath@gmail.com

2007-08-19, 7:10 pm

I am trying to understand a code that had its origin since FORTRAN IV
days (1970's I guess).

A particular line tries to read values from a binary tape. In loop
100, "L" values are skipped. Note that there are no variables after
the read statement. Then an array of values is read afterwards.

DO 100 ISKIP =1,L
100 READ (INTAPE)
READ (INTAPE) (VALUES(I),I=1,N)

I replaced the above code by the following.

DO 100 ISKIP =1,L
100 READ (INTAPE) (VALUES(I),I=1,N)
READ (INTAPE) (VALUES(I),I=1,N)

>From theory I guessed what the code was doing, but could not

understand why there are no variables after READ statement.

Both these statements produce the same answer. I get the same values
in the VALUES array. In both cases L and N have values greater than 1.

How does FORTRAN compiler know that it has to read a list of values
when there are no variables specified after READ statement? While the
values are written to INTAPE, they are always written as WRITE(INTAPE)
(VALUES(I),I=1,N). Are there any special characters printed in binary
tape that tell the compiler that the list of values is actually a
single variable ? Its a little confusing for me.

I have one more question too: The entire program uses one variable.
COMMON Z(20000000)
DIMENSION EXPAND(1),WW(1),AP(1)

All the other variables are defined as sub arrays with dimension 1.
Z(201) is passed as EXPAND(1) and so on. Is there a limitation on this
number 20000000? Is that the maximum array size that can be defined in
Windows or Linux or How can I determine the maximum array size in a
program?

Finally, is there a good FORTRAN IV book that will explain to me some
of the unique FORTRAN IV commands? I am not entirely happy with the
use of GO TO statements in place of IF, then syntax.

Could someone familier with the above offer some insights? Any help
will be appreciated.

Richard Maine

2007-08-19, 7:10 pm

On Sun, 19 Aug 2007 15:01:09 -0700, ssragunath@gmail.com wrote
(in article <1187560869.936754.136380@19g2000hsx.googlegroups.com> ):

> DO 100 ISKIP =1,L
> 100 READ (INTAPE)
> READ (INTAPE) (VALUES(I),I=1,N)
>
> I replaced the above code by the following.
>
> DO 100 ISKIP =1,L
> 100 READ (INTAPE) (VALUES(I),I=1,N)
> READ (INTAPE) (VALUES(I),I=1,N)
>
> From theory I guessed what the code was doing, but could not
> understand why there are no variables after READ statement.


> Both these statements produce the same answer. I get the same values
> in the VALUES array. In both cases L and N have values greater than 1.
>
> How does FORTRAN compiler know that it has to read a list of values
> when there are no variables specified after READ statement? While the
> values are written to INTAPE, they are always written as WRITE(INTAPE)
> (VALUES(I),I=1,N). Are there any special characters printed in binary
> tape that tell the compiler that the list of values is actually a
> single variable ? Its a little confusing for me.


I don't understand why you changed it. I see no advantage to the change. I
suggest changing it back to the original.

This is part of what records are about. For unformatted I/O, each read or
write statement reads or writes a single record. It reads or writes the whole
record. If there are no variables in the input list on a read, that
essentially just skips the record, which is exactly what you want. I see no
point to reading in values that you are going to ignore (by immediately
overwriting them).

The underlying implementation details are up to the compiler and/or operating
system. You aren't supposed to have to worry about them unless you are doing
something out of the ordinary (notably trying to interoperate with
non-Fortran stuff or different Fortran compilers). You just need to know that
it is handled for you. That being said, the most common implementations today
but a record-length header at the beginning of the record (and a similar
trailer at the end to support backspacing). That header (and trailer) is
invisible to you in normal Fortran code.

> I have one more question too: The entire program uses one variable.
> COMMON Z(20000000)
> DIMENSION EXPAND(1),WW(1),AP(1)
>
> All the other variables are defined as sub arrays with dimension 1.
> Z(201) is passed as EXPAND(1) and so on.


Yes. That's a typical practice for Fortran of that vintage. It is technically
nonstandard, but there weren't any good alternatives, so that's what people
did. Modern Fortran code wouldn't be done this way. If you have to work with
an old code (as you say is the case), then so be it. But don't take this as a
model for how to write new code.

Is there a limitation on this
> number 20000000? Is that the maximum array size that can be defined in
> Windows or Linux or How can I determine the maximum array size in a
> program?


Those things depend entirely on the compiler and OS. There isn't any standard
specification of the maximum or way to determine it other than reading the
compiler docs. That being said, most 32-bit compilers/systems can't deal with
programs that use more than 2 GB of memory (or sometimes perhaps 4 GB). And
sometimes you see the same limit on 64-bit systems in some cases.

> Finally, is there a good FORTRAN IV book that will explain to me some
> of the unique FORTRAN IV commands?


You aren't going to find a Fortran IV book today, good or otherwise, unless
perhaps you go looking on eBay or some such place. The language has been
obsolete for nearly 3 decades (or perhaps more, depending on precisely what
you mean by "Fortran IV" - that term is sometimes used with slightly
different meanings).

Most newer Fortran books will be adequate to explain what most of the
statements (by the way, they are "statements", not "commands") of the
language mean, though they will also cover a lot of stuff that wasn't in
Fortran IV. There are a few features that were deleted as of Fortran 77; you
might not find them covered in newer texts.

--
Richard Maine


________________________________________
________

Hogwasher, Premier News and Mail for OS X
http://www.asar.com/cgi-bin/product.../hogwasher.html
________________________________________
________

glen herrmannsfeldt

2007-08-19, 7:10 pm

ssragunath@gmail.com wrote:
> I am trying to understand a code that had its origin since FORTRAN IV
> days (1970's I guess).


> A particular line tries to read values from a binary tape. In loop
> 100, "L" values are skipped. Note that there are no variables after
> the read statement. Then an array of values is read afterwards.

(snip)

> 100 READ (INTAPE)

(snip)

> 100 READ (INTAPE) (VALUES(I),I=1,N)

(snip)

> understand why there are no variables after READ statement.


Unformatted I/O is record oriented. Each WRITE writes one record,
each READ reads one record. One should be careful not to read more
(a longer record) than was written, but reading only part of a record
is allowed. On some systems, the record structure is part of the
file system. (That was more common in the early days of Fortran.)
On systems without a record oriented file system, it is usually
done with length indicators in the file.

> Both these statements produce the same answer. I get the same values
> in the VALUES array. In both cases L and N have values greater than 1.


Yes.

> How does FORTRAN compiler know that it has to read a list of values
> when there are no variables specified after READ statement? While the
> values are written to INTAPE, they are always written as WRITE(INTAPE)
> (VALUES(I),I=1,N). Are there any special characters printed in binary
> tape that tell the compiler that the list of values is actually a
> single variable ? Its a little confusing for me.


It is system dependent how it is done, but it must be done.

> I have one more question too: The entire program uses one variable.
> COMMON Z(20000000)
> DIMENSION EXPAND(1),WW(1),AP(1)


> All the other variables are defined as sub arrays with dimension 1.
> Z(201) is passed as EXPAND(1) and so on. Is there a limitation on this
> number 20000000? Is that the maximum array size that can be defined in
> Windows or Linux or How can I determine the maximum array size in a
> program?


The limits are system dependent, depending on both the compiler and
available memory when the program is run.

(snip)

-- glen

Terence

2007-08-19, 7:10 pm

You did not show how the file designated by INTAPE was opened, or what
king of varibale is the variable "VALUES".
Since there is no format associated with the read, it will be a binary
record input on each read fromm the device associated with the unit
number "INTAPE".


> DO 100 ISKIP =1,L
> 100 READ (INTAPE)


This skips L records, not L values.
The end of a record was specified by an end-record code on the tape or
disk used for storage.
Records could be all of constant fixed length or of variable lengths.

The content of each record is unspecified but could contain any number
of values, probably integers or text occupying integer widths,
(typically 4 characters per 32 bit word).
I guess text because they are being skipped and so may be descriptive
only.

> READ (INTAPE) (VALUES(I),I=1,N)


This then reads ONE record and treats it as N values, unless there are
less than N values in the record, in which case it will read the next
records and continue extracting values until N have been read. There
may be MORE than N values in the ONE record, but the read takes the
first N of them, determined by whatever the variable array VALUES
means. This could be integers, but more likely to be an array of
REAL*4 or even REAL*8, since in Fortran IV it was common for integers
to start with I,J,K,L,M or N and anything else would be real
variables.

>
> I replaced the above code by the following.
>
> DO 100 ISKIP =1,L
> 100 READ (INTAPE) (VALUES(I),I=1,N)
> READ (INTAPE) (VALUES(I),I=1,N)


This was a mistake. The intent was to skip L records not L*N values.
But it would work if the records lengths were fixed and equated to N
values of type VALUES per record. Only the last read, overwriting all
the previous reads you included would then provide the FINAL values of
"VALUES" that were used in the calculations.

Gordon Sande

2007-08-19, 7:10 pm

On 2007-08-19 19:01:09 -0300, ssragunath@gmail.com said:

> I am trying to understand a code that had its origin since FORTRAN IV
> days (1970's I guess).
>
> A particular line tries to read values from a binary tape. In loop
> 100, "L" values are skipped. Note that there are no variables after
> the read statement. Then an array of values is read afterwards.
>
> DO 100 ISKIP =1,L
> 100 READ (INTAPE)
> READ (INTAPE) (VALUES(I),I=1,N)
>
> I replaced the above code by the following.
>
> DO 100 ISKIP =1,L
> 100 READ (INTAPE) (VALUES(I),I=1,N)
> READ (INTAPE) (VALUES(I),I=1,N)
>
> From theory I guessed what the code was doing, but could not
> understand why there are no variables after READ statement.
>
> Both these statements produce the same answer. I get the same values
> in the VALUES array. In both cases L and N have values greater than 1.
>
> How does FORTRAN compiler know that it has to read a list of values
> when there are no variables specified after READ statement? While the
> values are written to INTAPE, they are always written as WRITE(INTAPE)
> (VALUES(I),I=1,N). Are there any special characters printed in binary
> tape that tell the compiler that the list of values is actually a
> single variable ? Its a little confusing for me.



> Could someone familier with the above offer some insights? Any help
> will be appreciated.


The Fortran I/O model is record based. So you can read all of the record,
part of the reocord or none of the record and the I/O system will skip
forward to the end of the record. The next read will see the same next
record in all cases.

As you have discovered this can be used to effectively in some circumstances.

Your "correction" made no change as there was nothing to fix. It will
increase the overhead but the increase will only be apparent if you
are able to time things accurately to machine cycles.

The record model also allows for backspacing. In practice it requires that
there be length indicators associated with each record. These are often the
initial several bytes of each record. Lengths at the end can help with
backspacing. Sometimes the operating system does this extra bookkeeping for
free. Such an operating system is rarely named Unix or some close equivalent.
Systems that do not have this structure are often called byte streams. C
commonly uses such a model so the features of a record based system seem
strange to those who have only been exposed to C as if it were the definitive
design. It is just one possible design, not the only possible one.



Louis Krupp

2007-08-19, 7:10 pm

ssragunath@gmail.com wrote:
> I am trying to understand a code that had its origin since FORTRAN IV
> days (1970's I guess).
>
> A particular line tries to read values from a binary tape. In loop
> 100, "L" values are skipped. Note that there are no variables after
> the read statement. Then an array of values is read afterwards.
>
> DO 100 ISKIP =1,L
> 100 READ (INTAPE)
> READ (INTAPE) (VALUES(I),I=1,N)
>
> I replaced the above code by the following.
>
> DO 100 ISKIP =1,L
> 100 READ (INTAPE) (VALUES(I),I=1,N)
> READ (INTAPE) (VALUES(I),I=1,N)
>
> understand why there are no variables after READ statement.
>
> Both these statements produce the same answer. I get the same values
> in the VALUES array. In both cases L and N have values greater than 1.
>
> How does FORTRAN compiler know that it has to read a list of values
> when there are no variables specified after READ statement? While the
> values are written to INTAPE, they are always written as WRITE(INTAPE)
> (VALUES(I),I=1,N). Are there any special characters printed in binary
> tape that tell the compiler that the list of values is actually a
> single variable ? Its a little confusing for me.


Never change code that's older than you are. :)

Here's the story on the READ statement:

Your input file is structured as a sequence of records. In the most
likely scenario, another program did something like this:

WRITE (OUTTAPE) VALUES(I),I=1,N

Assume that VALUES is declared INTEGER and that integers default to four
bytes.

The FORTRAN run-time library (the bit that actually implements things
like READ and WRITE) wrote a four-byte word with the record length (most
likely N * 4) followed by N four-byte elements of VALUES.

When you read the logical unit INTAPE, it reads one record (all N
values). When you read with no variable list, it skips one record
(rather than one value). Reading VALUES(I),I=1,N and ignoring them is
just a slightly slower way of doing the same thing.

Out of curiosity, what operating system are you using?

>
> I have one more question too: The entire program uses one variable.
> COMMON Z(20000000)
> DIMENSION EXPAND(1),WW(1),AP(1)
>
> All the other variables are defined as sub arrays with dimension 1.
> Z(201) is passed as EXPAND(1) and so on. Is there a limitation on this
> number 20000000? Is that the maximum array size that can be defined in
> Windows or Linux or How can I determine the maximum array size in a
> program?


That maximum size is system-dependent. Fortran 95 will let you allocate
arrays dynamically if you don't know the size at compile time.

>
> Finally, is there a good FORTRAN IV book that will explain to me some
> of the unique FORTRAN IV commands? I am not entirely happy with the
> use of GO TO statements in place of IF, then syntax.


I believe (and I'm sure I'll be corrected) that FORTRAN IV is an
"unstandardized" version of FORTRAN 66 which is a subset of FORTRAN 77
which is mostly a subset of Fortran 90 which is a subset of Fortran 95
which in turn is a subset of Fortran 2003. You might not need (or want)
a FORTRAN IV manual. A Fortran 95 book *should* explain stuff like GO
TO statements. If you don't want to wade through all the new stuff, or
if you just like things that are old, you should be able to buy Daniel
McCracken's "Guide to FORTRAN IV Programming" dirt cheap on Amazon.

Then buy a Fortran 95 book for your new code. And Fortran 2003
compilers are on the way.

Louis
Terence

2007-08-19, 10:12 pm

I missed that bit about the large COMMON area.

The code is for a LARGE mainframe computer and the use of that COMMON
area "Z" is a very common way of defining a general problam as having
various combinations of sizes of arrays, and "carving" off chunks of a
single area (Z), just as you indicated.
The most famous set I remember as showing this, was the Universityy
College of Los Angeles scientific statistical package suite "BMD".

To usee it, you specified the size of the dimensions of the problem
matices as answers to questions in the MAIN program, which then
allocated the useage of the single memory block and passed the start
point indices to all subroutines. A very usful trick.

ssragunath@gmail.com

2007-08-19, 10:12 pm

Thanks everyone for taking time to offer input / explanations.

* >> Never change code that's older than you are. :)
I agree and I learnt my lesson. I understand why it was done that way
thanks to all your input. The old way is very efficient and brilliant.

* >> Out of curiosity, what operating system are you using?
This code was originally done on VAX, HP-UNIX and SOLARIS. Over years
it changed many platforms and compilers. I had started porting it to
Windows using Intel Fortran 9.1 Compiler (testing it).

* The files are opened as OPEN
(INTAPE,FILE='tape1.bin',FORM='unformatted')

* This code is the combined efforts of a few PhD students in a famous
California University starting in 1970's. Out of respect to the
brilliant minds that had worked on this code, I am not going to name
the program. The variables are mostly double precision complex
(COMPLEX*16 now ?).

The common storages are defined this way
COMMON Z(20000000)
COMMON /IZATO/IZ(20000000)
MTOTL = 20000000
If the storage computed is greater than MTOTL, then the program prints
an error and exits.

The main issue is to increase the capacity of the program. Because the
entire code is based on Block Common Storage, is there any way to
dynamically allocate the memory in COMMON statement? I had used
pointers in C++ in one of my grad programs, but dynamic allocation in
FORTRAN is new game for me. So my knowledge is very limited on this
topic.

Is there any way to dynamically allocate the storage and still
maintain the old code format? Isn't the dynamic allocation also bound
by the 2GB memory barrier in Win systems? Going by C++ syntax, I am
afraid that if I do dynamic allocation I might have to rewrite the way
variables are referenced in the time tested program.

Thanks.

glen herrmannsfeldt

2007-08-19, 10:12 pm

Louis Krupp wrote:

(snip)

> The FORTRAN run-time library (the bit that actually implements things
> like READ and WRITE) wrote a four-byte word with the record length (most
> likely N * 4) followed by N four-byte elements of VALUES.


That is what it does on some systems. On others, the record length
is part of the file system. IBM mainframe systems and VMS have
file systems that keep the record length as part of the file.

It seems that this one started on VAX/VMS.

-- glen

glen herrmannsfeldt

2007-08-20, 4:33 am

Richard Maine wrote:

> On Sun, 19 Aug 2007 15:01:09 -0700, ssragunath@gmail.com wrote


(snip)

[color=darkred]
[color=darkred]
> Yes. That's a typical practice for Fortran of that vintage. It is technically
> nonstandard, but there weren't any good alternatives, so that's what people
> did. Modern Fortran code wouldn't be done this way. If you have to work with
> an old code (as you say is the case), then so be it. But don't take this as a
> model for how to write new code.


Dimensioning the arrays (1) is non-standard, but if you dimension
them with the appropriate length it should be standard. I have seen
programs that pass the length and still dimension (1).

(snip)

-- glen

Beliavsky

2007-08-20, 4:37 am

On Aug 19, 5:31 pm, Richard Maine <nos...@see.signature> wrote:

<snip>

> You aren't going to find a Fortran IV book today, good or otherwise, unless
> perhaps you go looking on eBay or some such place. The language has been
> obsolete for nearly 3 decades (or perhaps more, depending on precisely what
> you mean by "Fortran IV" - that term is sometimes used with slightly
> different meanings).


Richard Maine's advice is good, but let me mention that there are at
least 48 books on Fortran IV listed on Amazon, and most are available
used at a reasonable price.

Richard Maine

2007-08-20, 4:41 am

On Sun, 19 Aug 2007 19:43:06 -0700, ssragunath@gmail.com wrote
(in article <1187577786.885942.297820@k79g2000hse.googlegroups.com> ):

> The main issue is to increase the capacity of the program. Because the
> entire code is based on Block Common Storage, is there any way to
> dynamically allocate the memory in COMMON statement? I had used
> pointers in C++ in one of my grad programs, but dynamic allocation in
> FORTRAN is new game for me. So my knowledge is very limited on this
> topic.
>
> Is there any way to dynamically allocate the storage and still
> maintain the old code format? Isn't the dynamic allocation also bound
> by the 2GB memory barrier in Win systems? Going by C++ syntax, I am
> afraid that if I do dynamic allocation I might have to rewrite the way
> variables are referenced in the time tested program.


Sorry, but common and dynamic allocation don't mix well. Dynamic allocation
is easy in modern Fortrans. But converting old code that used schemes like
that isn't necessarily easy. If you can find a single top-level place where
each array is initially set up, you might be able to substitute something
like an allocatable array there, and forget the common. But it is hard to say
whether that is practical without seeing the code.

Yes, dynamic memory is also bound by the 2 GB barrier.

--
Richard Maine | Good judgement comes from experience;
email: last name at domain . net | experience comes from bad judgement.
domain: summertriangle | -- Mark Twain


________________________________________
________

Hogwasher, Premier News and Mail for OS X
http://www.asar.com/cgi-bin/product.../hogwasher.html
________________________________________
________

Louis Krupp

2007-08-20, 8:23 am

glen herrmannsfeldt wrote:
> Louis Krupp wrote:
>
> (snip)
>
>
> That is what it does on some systems. On others, the record length
> is part of the file system. IBM mainframe systems and VMS have
> file systems that keep the record length as part of the file.
>
> It seems that this one started on VAX/VMS.


I believe that FORTRAN can create variable length records, with the
record length depending on how much is written. I vaguely remember the
Burroughs Large Systems MCP having attributes like MAXRECSIZE, which
does just what one would expect, and FILETYPE, an enumerated attribute
one of whose values indicates FORTRAN variable length records
implemented by "link" (?) words that store the lengths of the previous
and next records.

I'm sure that it is possible (on UNISYS MCP systems and on VMS) to
create files with different attributes and have a Fortran program write
fixed-length records. I just don't recall the details. The scary thing
is that while I haven't used anything from Unisys in almost 20 years, I
think I remember more of that than I do of VMS.

Louis
glen herrmannsfeldt

2007-08-20, 8:23 am

Louis Krupp wrote:

> glen herrmannsfeldt wrote:


(snip on UNFORMATTED I/O)

[color=darkred]
[color=darkred]
> I believe that FORTRAN can create variable length records, with the
> record length depending on how much is written. I vaguely remember the
> Burroughs Large Systems MCP having attributes like MAXRECSIZE, which
> does just what one would expect, and FILETYPE, an enumerated attribute
> one of whose values indicates FORTRAN variable length records
> implemented by "link" (?) words that store the lengths of the previous
> and next records.


Yes they can be variable size. OS/360 (and continuing to the current
z/OS) have a special record format, VBS, which I believe was created
especially for Fortran. That is, Variable Blocked Spanned, which
allows records to be longer than a disk track. I have done something
similar to:

WRITE(1) N,(X(I),I=1,N),(Y(I),I=1,N)

where N is written in the same record, and can be read
with the corresponding READ statement.

> I'm sure that it is possible (on UNISYS MCP systems and on VMS) to
> create files with different attributes and have a Fortran program write
> fixed-length records. I just don't recall the details. The scary thing
> is that while I haven't used anything from Unisys in almost 20 years, I
> think I remember more of that than I do of VMS.


OS/360 and successors use fixed length (FB) for formatted I/O, with
popular lengths being 80 characters (card images) and 133 for
printed output (132 plus carriage control). Records are blank padded
on output, with an error if too much data is written.

-- glen

John Harper

2007-08-20, 7:10 pm

In article <1187577786.885942.297820@k79g2000hse.googlegroups.com>,
<ssragunath@gmail.com> wrote:
>... The variables are mostly double precision complex
>(COMPLEX*16 now ?).


COMPLEX(KIND(1d0)) is better: not only is the relevant number not 16 in
some compilers, but that * form of declaration is non-standard except
for CHARACTER, and even there it's obsolescent.

Better still, of course, is something like
INTEGER,PARAMETER :: DP=SELECTED_REAL_KIND(15)
COMPLEX(DP) ...

because the chances are you'll want REAL(DP) as well, and if you change
to a system whose single precision is as good as your previous one's
double, then your program will need no changes provided you have put
the declaration of DP either in a USEd module or in each main program
and external subprogram, and _DP on each real literal constant, e.g.
REAL(DP):: pi=3.141592653589793_DP, million=1e6_DP ! NOT 1d6_DP

-- John Harper, School of Mathematics, Statistics and Computer Science,
Victoria University, PO Box 600, Wellington 6140, New Zealand
e-mail john.harper@vuw.ac.nz phone (+64)(4)463 5341 fax (+64)(4)463 5045
Terence

2007-08-20, 7:10 pm

Since the question was clarified as to being from a Univeristy of
California, and if it WAS UCLA and the code IS BMD or BMDP (which uses
the same exact technique), then YES, you can change the allocation in
the first Main module and continue from there.

I know because I still have some of the code (since 1972, althought
the 1600 bpi tape is now unreadable) and I made those changes to get
working modules in F77. But I have newer public code (BMDP is
considered private, BMD public, all still in the University Library at
Stanford).

glen herrmannsfeldt

2007-08-20, 10:10 pm

Terence wrote:
(snip)

> I know because I still have some of the code (since 1972, althought
> the 1600 bpi tape is now unreadable)


Have you tried? 1600 BPI tapes are much better than 800 at lasting
longer and/or being readable on different drives.

-- glen

Sponsored Links







Also available: Server administration forum archive | Web Design forum archive | Software forum archive | Hardware reviews archive

Copyright 2008 codecomments.com