Code Comments
Programming Forum and web based access to our favorite programming groups.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.
Post Follow-up to this messageOn 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 whol e 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 operatin g 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 tha t it is handled for you. That being said, the most common implementations toda y 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 technicall y 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 standar d 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 wit h 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 ________________________________________ ________
Post Follow-up to this messagessragunath@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
Post Follow-up to this messageYou 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.
Post Follow-up to this messageOn 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 definitiv e design. It is just one possible design, not the only possible one.
Post Follow-up to this messagessragunath@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
Post Follow-up to this messageI 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.
Post Follow-up to this messageThanks 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.
Post Follow-up to this messageLouis 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
Post Follow-up to this messageRichard Maine wrote: > On Sun, 19 Aug 2007 15:01:09 -0700, ssragunath@gmail.com wrote (snip) > Yes. That's a typical practice for Fortran of that vintage. It is technica lly > nonstandard, but there weren't any good alternatives, so that's what peopl e > did. Modern Fortran code wouldn't be done this way. If you have to work wi th > an old code (as you say is the case), then so be it. But don't take this a s 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
Post Follow-up to this messagePowered by vBulletin
Copyright 2000-2006 Jelsoft Enterprises Limited.