Table of Contents
This is an old revision of the document!
Ratfor90
- You can download ratfor90 from here.
Introduction/Description
“Ratfor” is a dialect of Fortran that is more concise than raw Fortran. The newest Ratfor “compiler”, ratfor90 is a simple preprocesor program written in Perl that inputs an attractive Fortran-like dialect and outputs Fortran90. Mainly, the preprocessor produces Fortran statements like “ end do ”, “end if”, “end program”, and “end module”, from the Ratfor “}”. Ratfor source is about 25-30% smaller than the equivalent Fortran making it equivalently more readable.
Bare-bones Fortran is our most universal computer language for computational physics. For general programming, however, it has been surpassed by C. Ratfor is Fortran with C-like syntax. Ratfor was invented by the people who invented C. After inventing C, they realized that they had made a mistake (too many semicolons) and they fixed it in Ratfor, although it was too late for C. Otherwise, Ratfor uses C-like syntax, the syntax that is also found in the popular languages C++ and Java .
At SEP we supplemented Ratfor77 by preprocessors to give Fortran77 the ability to allocate memory on the fly. These abilities are built into Fortran90 and are seamlessly included in Ratfor90. To take advantage of Fortran90's new features while maintaining the concise coding style provided by Ratfor required us to write a new Ratfor preprocessor, Ratfor90, which produces Fortran90, rather than Fortran77 code.
You should be able to read Ratfor if you already know Fortran or any similar computer language. Writing Ratfor is easy if you already know Fortran. In general written Fortran is valid Ratfor, the only. Ratfor uses C style definition of lines and {} for expanded statements. To maximize the amount of Ratfor, you will need to know its rules. Here they are:
Statements on a line may be separated by “;”. Statements may be grouped together with braces “{ }”. Do loops do not require statement numbers because “{ }” defines the range. Given that “if( )” is true, the statements in the following { } are done. “ else{ }” does what you expect. We may not contract “ else if ” to “ elseif”. We may omit the braces { } where they contain only one statement. “break” (equivalent to the Fortran90 “ exit”) causes premature termination of the enclosing { }. “while( ) { }” repeats the statements in { } while the condition ( ) is true. Ratfor recognizes a looping statement more general than “do”. It is “for(initialize; condition; reinitialize){ }”. “ repeat { … } until( )” is a loop that tests at the bottom. “next” causes skipping to the end of any loop and a retrial of the test condition. “ next” (equivalent to the Fortran90 “cycle” statement) is rarely used, and the Ratfor90 programer may write either “next” or “cycle”. With the “ cycle ” statement we encounter an inconsistency between Fortran and C-language. Where Ratfor uses “next”, the C-language uses “continue” (which in Ratfor and Fortran is merely a place holder for labels). The Fortran relational operators “.gt., ge., .ne. ”, etc. may be written “>, >=, !=,” etc. The logical operators “.and.” and “.or.” may be written “&&” and “||”. Anything from a # to the end of the line is a comment. A line may be continued in Ratfor by ending it with the underscore charactor “” _“'' or Fortran90's ”&“.
Indentation in Ratfor is used for readability. It is not part of the Ratfor language. Choose your own style. There are two pitfalls associated with indentation. The beginner's pitfall is to assume that a “do” loop ends where the indentation ends. The loop actually ends after the first statement. A larger scope for the “do” loop is made by enclosing multiple statements in braces. The other pitfall arises in any construction like “if() … if() … else”. The “else” goes with the last “if()” regardless of indentation. If you want the “else” with the earlier “if()”, you must use braces like “if() { if() … } else …”.
Changes and general backward compatibility issues
There are two rarely used features of Ratfor77 that were not implemented in Ratfor90. ” break 2 “ which escapes from { { } }. This feature can easily be replaced by the loop naming features supported in Fortran90. Ratfor77 allows & and | for the logical operators && and ||. While attractive, it is not part of the C family of languages and we had to drop it because Fortran90 adopts & for line continuation.
Changing all the code that generated illustrations for four textbooks (of various ages) also turned up a few more issues: Fortran90 uses the words “scale” and “matmul” as intrinsics. Old Fortran77 programs using those words as variable names must be changed. Ratfor77 unwisely allowed variables of intrinsic (undeclared) types. We no longer allow this. Ratfor90 forces ” implicit none“.
In Ratfor90 bracketed “type, subroutine, function,” and “module procedures” are interpreted. In some ways this a further step towards the C, C++, Java model. It makes complicated modules, subroutines inside subroutines, and other advanced features of Fortran90 easier to interpret. Ratfor90 recognizes “a+=b” as “a=a+b” and the similar construct ”-=“. Ratfor90 has better error messages than Ratfor77. Besides using stderr, a new file (“ratfor_problem”) marks the difficulty. In addition, the output of Ratfor90 is much more readable than the Ratfor77 version.
SEP-specific backward compatibility issues
SEP has a considerable amount of legacy Ratfor77 code which used two home-grown preprocessors to get around Fortran77's memory allocation problems. Ratfor90 allows the conventions established by these preprocessors, interpreting them into standard Fortran90.
Memory allocation in subroutines
For backward compatibility we allow the “temporary” memory allocation introduced by our Ratfor77 processor for example:
” temporary real*4 data(n1,n2,n3), convolution(j+k-1)“
These declarations must follow other declarations and precede the executable statements. Automatic arrays are supported in Fortran90. To allow full code compatibility “Ratfor90” simply translates this statement to
” real*4 data(n1,n2,n3), convolution(j+k-1)“.
Examples
Below are two simple Ratfor subroutines for finding the signum function sgn(x) = |x| (“signum()”), and (“tcaf”) a fortran90 module that uses overloading to transient convolution.
Math funcion
Transient convolution
The main program environment
“Ratfor90” supports some traditional SEP local memory allocation and data base I/O statements. In addition it calls an essential seplib initialization routine ” initpar()“, organizes the self-doc, and simplifies data-cube input. The basic syntax for memory allocation is “allocate: real x(n1,n2)”. “Ratfor90” translates this syntax into a call to dynamically allocate a “allocatable” array. See the on-line self-documentation or the manual pages for full details. Following is a complete Ratfor program for a simple task:
# out.H # # Copy input to output and scale by scaleval # keyword generic scale #% integer n1, n2, n3, esize from history: integer n1, n2, n3, esize if (esize !=4) call erexit('esize != 4') allocate: real x(n1,n2) subroutine scaleit( n1,n2, x) integer i1,i2, n1,n2 real x(n1,n2), scaleval from par: real scaleval=1. call hclose() # no more parameter handling. call sreed('in', x, 4*n1*n2) do i1=1,n1 do i2=1,n2 x(i1,i2) = x(i1,i2) * scaleval call srite( 'out', x, 4*n1*n2) return; end
Downloading/Installing
You can download ratfor90 from here. You might need to change the first line of the code indicating where perl is on your system.
You can convert from Ratfor90 to Fortran90 on the command line by:
prompt%ratfor90 < input.r90 > output.f90
If you wish to use expanded SEP comand line, history file manipulation, and self-documentation abilities add the ” -sep -SOURCE /my/source/location “ flags.
- set the enviornmental variable RATF90 to yes (” setenv RATF90 yes“).If you are using the SEP setup you can add this line to your Setup/cshrc.machinetype [e.g. cshrc.sgi, cshrc.i586, etc.]
- name your Ratfor90 files:
- using Fortran90 syntax .r90.
- using Fortran90 and SEP allocation conventions .rs90.
These rules are an updated version of the SEP makefile rules so if you have downloaded a previous version you will still need to download this version.
Sample Output
Here is a Ratfor90 code that serves no useful purpose other than demonstrating a number of the features of ratfor
# # # test.x #% program test{ integer i1,i2,n1,n2,count real,pointer,dimension(:,:) :: input from either: integer n1=5,n2=5 allocate(input(n1,n2)) input=0.; count=0 loop1: do i2=1,n2{ for(i1=1; i1 <5 ; i1+=2){ count++ if(i1==3 && i2==4) break loop1 else input(i1,i2) += count } } where(input == 0) input=-15. write(0,*) input } And the resulting Fortran90 code: ! ! !test.x !% program test integer i1,i2,n1,n2,count real,pointer,dimension(:,:) :: input integer fetch, putch call initpar() call doc('/homes/sep/bob/test.rs90') if (0==fetch('n1','d',n1))then n1=5 end if if (0/=putch('From either: n1','d',n1))then call seperr('trouble writing n1 to history file') end if if (0==fetch('n2','d',n2))then n2=5 end if if (0/=putch('From either: n2','d',n2))then call seperr('trouble writing n2 to history file') end if allocate(input(n1,n2)) input=0. count=0 loop1: do i2=1,n2 i1=1 do if( .not. (i1<5)) then exit end if count = count+1 do if( .not. (i1<5)) then exit end if count = count+1 if (i1 .eq. 3 .and. i2 .eq. 4)then exit loop1 else input(i1,i2) = input(i1,i2) + count end if i1=i1+2 end do end do loop1 where(input .eq. 0) input=-15. end where write(0,*) input end program
References
Claerbout, J., 1990, Introduction to “seplib” and SEP utility software: SEP-70, 413-436.
Claerbout, J., 1986, A canonical program library: SEP-50, 281-290.
Cole, S., and Dellinger, J., Vplot: SEP's plot language: SEP-60, 349-389.