This appendix shows some of the major features differences between:
Standard Fortran 90 and Sun Fortran 90
FORTRAN 77 and Fortran 90
Sun Fortran 90 provides the following features.
f90 allows the tab character in fixed-form source and in free-form source. Standard Fortran 90 does not allow tabs.
The tab character is not converted to a blank, so the visual placement of tabbed statements depends on the utility you use to edit or display text.
For a tab in column one:
If the next character is a nonzero digit, then the current line is a continuation line; otherwise, the current line is an initial line.
A tab cannot precede a statement label.
A tab after column one is treated by f90 the same as a blank character, except in literal strings.
f90 treats a tab and a blank character as equivalent, except in literal strings.
f90 and f77 allow 99 continuation lines (1 initial and 98 continuation lines). Standard Fortran 90 allows 19 for fixed-form and 39 for free-form.
In fixed-form source, lines can be longer than 72 characters. Columns 73 through 96 are ignored. Standard Fortran 90 allows 72-character lines.
f90 allows directive lines starting with CDIR$, !DIR$, CMIC$, or !MIC$. They look like comments but are not. For full details on directives, see "Directives". Standard Fortran 90 has no directives.
The tab form source text is defined as follows:
A tab in any of columns 1 through 6 makes the line as a tab form source line.
A comment indicator or a statement number may precede the tab.
If a tab is the first nonblank character, then:
If the character after the tab is anything other than a nonzero digit, then the text following the tab is an initial line.
If there is a nonzero digit after the first tab, the line is a continuation line. The text following the nonzero digit is the next part of the statement.
The default maximum line length is 72 columns for fixed form and 132 for free form.
Example: The tab form source on the left is treated as shown on the right.
!^IUses of tabs ^ICHARACTER *3 A = 'A' ^IINTEGER B = 2 ^IREAL C = 3.0 ^IWRITE(*,9) A, B, C 9^IFORMAT(1X, A3, ^I1 I3, ^I2 F9.1 ) ^IEND ! Uses of tabs CHARACTER *3 A = 'A' INTEGER B = 2 REAL C = 3.0 WRITE(*,9) A, B, C 9 FORMAT(1X, A3, 1 I3, 2 F9.1 ) END
In the example above, "^I" is a way of indicating the tab character, and the line starting with "1" and "2" are continuation lines. The coding is shown to illustrate various tab situations, and not to advocate any one style.
The source form assumed by f90 depends on options, directives, and suffixes.
Table C-1 F90 Source Form Command-line options
Option |
Action |
---|---|
-fixed |
Interpret all source files as Fortran fixed form |
-free |
Interpret all source files as Fortran free form |
If the -free or -fixed option is used, that overrides the file name suffix.
Table C-2 F90 File name suffixes
Suffix |
Source Form |
---|---|
.f90 |
Fortran free-form source files |
.f |
Fortran fixed-form source files or ANSI standard FORTRAN 77 source files |
.for |
Same as .f. |
.ftn |
Same as .f. |
other |
None--file name is passed to the linker |
If either a FREE or FIXED directive is used, that overrides the option and file name suffix.
Some mixing of source forms is allowed.
In the same f90 command, some source files can be fixed form, some free.
In the same file, free form can be mixed with fixed form by using directives.
In the same program unit, tab form can be mixed with free or fixed form.
Sun Fortran 90 is case insensitive. That means that a variable AbcDeF is treated as if it were spelled abcdef, or abcdeF, etc. "Compatibility with FORTRAN 77"
f90 supports constants and expressions of Boolean type. There are no Boolean variables or arrays, and there is no Boolean type statement.
Masking-A bitwise logical expression has a Boolean result; each of its bits is the result of one or more logical operations on the corresponding bits of the operands.
For binary arithmetic operators, and for relational operators:
If one operand is Boolean, the operation is performed with no conversion.
If both operands are Boolean, the operation is performed as if they were integers.
No user-specified function can generate a Boolean result, although some (nonstandard) intrinsics can.
Boolean and logical types differ as follows:
Variables, arrays, and functions can be of logical type, but they cannot be Boolean type.
There is a LOGICAL statement, but no BOOLEAN statement.
A logical variable or constant represents only one value. A Boolean constant can represent as many as 32 values.
A logical expression yields one value. A Boolean expression can yield as many as 32 values.
Logical entities are invalid in arithmetic, relational, or bitwise logical expressions. Boolean entities are valid in all three.
f90 allows a Boolean constant (octal, hexadecimal, or Hollerith) in the following alternate forms (no binary). Variables cannot be declared Boolean. Standard Fortran does not allow these forms.
ddddddB, where d is any octal digit
You can use the letter B or b.
There can be 1 to 11 octal digits (0 through 7).
11 octal digits represent a full 32-bit word, with the leftmost digit allowed to be 0, 1, 2, or 3.
Each octal digit specifies three bit values.
The last (rightmost) digit specifies the content of the rightmost three bit positions (bits 29, 30, and 31).
If less than 11 digits are present, the value is right-justified--it represents the rightmost bits of a word: bits n through 31. The other bits are 0.
Blanks are ignored.
Within an I/O format specification, the letter B indicates binary digits; elsewhere it indicates octal digits.
X'ddd' or X"ddd", where d is any hexadecimal digit
There can be 1 to 8 hexadecimal digits (0 through 9, A-F).
Any of the letters can be uppercase or lowercase (X, x, A-F, a-f).
The digits must be enclosed in either apostrophes or quotes.
Blanks are ignored.
The hexadecimal digits may be preceded by a + or - sign.
8 hexadecimal digits represent a full 32-bit word and the binary equivalents correspond to the contents of each bit position in the 32-bit word.
If less than 8 digits are present, the value is right-justified--it represents the rightmost bits of a word: bits n through 31. The other bits are 0.
Accepted forms for Hollerith data are:
nH... |
'...'H |
"..."H |
nL... |
'...'L |
"..."L |
nR... |
'...'R |
"..."R |
Above, "..." is a string of characters and n is the character count.
A Hollerith constant is type Boolean.
If any character constant is in a bitwise logical expression, the expression is evaluated as Hollerith.
A Hollerith constant can have 1 to 4 characters.
Examples: Octal and hexadecimal constants.
Boolean Constant |
Internal Octal for 32-bit word |
---|---|
0B | 00000000000 |
77740B | 00000077740 |
X"ABE" | 00000005276 |
X"-340" | 37777776300 |
X'1 2 3' | 00000000443 |
X'FFFFFFFFFFFFFFFF' | 37777777777 |
Examples: Octal and hexadecimal in assignment statements.
i = 1357B |
---|
j = X"28FF" |
k = X'-5A' |
Use of an octal or hexadecimal constant in an arithmetic expression can produce undefined results and do not generate syntax errors.
f90 allows BOZ constants in the places other than DATA statements.
B'bbb' |
O'ooo' |
Z'zzz' |
B"bbb" |
O"ooo" |
Z"zzz" |
If these are assigned to a real variable, no type conversion occurs.
Standard Fortran allows these only in DATA statements.
f90 allows the following nonstandard type declaration forms in declaration statements, function statements, and IMPLICIT statements.
Table C-3 Size Notation for Numeric Data Types
Nonstandard |
Declarator |
Short Form |
Meaning |
---|---|---|---|
INTEGER*1 | INTEGER(KIND=1) | INTEGER(1) |
One-byte signed integers |
INTEGER*2 | INTEGER(KIND=2) | INTEGER(2) |
Two-byte signed integers |
INTEGER*4 | INTEGER(KIND=4) | INTEGER(4) |
Four-byte signed integers |
LOGICAL*1 | LOGICAL(KIND=1) | LOGICAL(1) |
One-byte logicals |
LOGICAL*2 | LOGICAL(KIND=2) | LOGICAL(2) |
Two-byte logicals |
LOGICAL*4 | LOGICAL(KIND=4) | LOGICAL(4) |
Four-byte logicals |
REAL*4 | REAL(KIND=4) | REAL(4) |
IEEE single-precision floating-point (Four-byte) |
REAL*8 | REAL(KIND=8) | REAL(8) |
IEEE double-precision floating-point (Eight-byte) |
COMPLEX*8 | COMPLEX(KIND=4) | COMPLEX(4) |
Single-precision complex (Four-bytes each part) |
COMPLEX*16 | COMPLEX(KIND=8) | COMPLEX(8) |
Double-precision complex (Eight-bytes each part) |
The form in column one is nonstandard Fortran 90, though in common use. The kind numbers in column two can vary by vendor.
A Cray pointer is a variable whose value is the address of another entity, which is called the pointee.
f90 supports Cray pointers; Standard Fortran 90 does not.
The Cray POINTER statement has the following format:
POINTER ( pointer_name, pointee_name [array_spec] ), ...
Where pointer_name, pointee_name, and array_spec are as follows:
pointer_name |
Pointer to the corresponding pointee_name. pointer_name contains the address of pointee_name. Must be: a scalar variable name (but not a structure) Cannot be: a constant, a name of a structure, an array, or a function |
pointee_name |
Pointee of the corresponding pointer_name Must be: a variable name, array declarator, or array name |
array_spec |
If array_spec is present, it must be explicit shape, (constant or nonconstant bounds), or assumed-size. |
Example: Declare Cray pointers to two pointees.
POINTER ( p, b ), ( q, c )
The above example declares Cray pointer p and its pointee b, and Cray pointer q and its pointee c.
Example: Declare a Cray pointer to an array.
POINTER ( ix, x(n, 0:m) )
The above example declares Cray pointer ix and its pointee x; and declares x to be an array of dimensions n by m-1.
You can use pointers to access user-managed storage by dynamically associating variables to particular locations in a block of storage.
Cray pointers allow accessing absolute memory locations.
Cray pointers do not provide convenient manipulation of linked lists because (for optimization purposes) it is assumed that no two pointers have the same value.
Cray pointers are declared as follows:
POINTER ( pointer_name, pointee_name [array_spec] )
Fortran pointers are declared as follows:
POINTER object_name
The two kinds of pointers cannot be mixed.
Whenever the pointee is referenced, f90 uses the current value of the pointer as the address of the pointee.
The Cray pointer type statement declares both the pointer and the pointee.
The Cray pointer is of type Cray pointer.
The value of a Cray pointer occupies one storage unit. Its range of values depends on the size of memory for the machine in use.
The Cray pointer can appear in a COMMON list or as a dummy argument.
The Cray pointee has no address until the value of the Cray pointer is defined.
If an array is named as a pointee, it is called a pointee array.
Its array declarator can appear in:
A separate type statement
A separate DIMENSION statement
The pointer statement itself
If the array declarator is in a subprogram, the dimensioning can refer to:
Variables in a common block, or
Variables that are dummy arguments
The size of each dimension is evaluated on entrance to the subprogram, not when the pointee is referenced.
If pointee_name is of character type, it must be a variable typed CHARACTER*(*).
If pointee_name is an array declarator, it must be explicit shape, (constant or nonconstant bounds), or assumed-size.
An array of Cray pointers is not allowed.
A Cray pointer cannot be:
Pointed to by another Cray pointer or by a Fortran pointer.
A component of a structure.
Declared to be any other data type.
A Cray pointer cannot appear in:
A PARAMETER statement or in a type declaration statement that includes the PARAMETER attribute.
A DATA statement.
A Cray pointee cannot appear in a SAVE, DATA, EQUIVALENCE, COMMON, or PARAMETER statement.
A Cray pointee cannot be a dummy argument.
A Cray pointee cannot be a function value.
A Cray pointee cannot be a structure or a structure component.
A Cray pointee cannot be of a derived type.
Cray pointees can be of type character, but their Cray pointers are different from other Cray pointers. The two kinds cannot be mixed in the same expression.
Cray pointers can be assigned values as follows:
Set to an absolute address
Example: q = 0
Assigned to or from integer variables, plus or minus expressions
Example: p = q + 100
Cray pointers are not integers. You cannot assign them to a real variable.
The LOC function (nonstandard) can be used to define a Cray pointer.
Example: p = LOC( x )
Example: Use Cray pointers as described above.
SUBROUTINE sub ( n ) COMMON pool(100000) INTEGER blk(128), word64 REAL a(1000), b(n), c(100000-n-1000) POINTER ( pblk, blk ), (ia, a ), ( ib, b ), & ( ic, c ), ( address, word64 ) DATA address / 64 / pblk = 0 ia = LOC( pool ) ib = ia + 1000 ic = ib + n ...
Remarks about the above example:
word64 refers to the contents of absolute address 64
blk is an array that occupies the first 128 words of memory
a is an array of length 1000 located in blank common
b follows a and is of length n
c follows b
a, b, and c are associated with pool
word64 is the same as blk(17) because Cray pointers are byte address and the integer elements of blk are each 4 bytes long
For purposes of optimization, f90 assumes the storage of a pointee is never overlaid on the storage of another variable--it assumes that a pointee is not associated with another variable.
Such association could occur in either of two ways:
A Cray pointer has two pointees, or
Two Cray pointers are given the same value
The programmer is responsible for preventing such association.
These kinds of association are sometimes done deliberately, such as for equivalencing arrays, but then results can differ depending on whether optimization is turned on or off.
Example: b and c have the same pointer.
POINTER ( p, b ), ( p, c ) REAL x, b, c p = LOC( x ) b = 1.0 c = 2.0 PRINT *, b ...
Above, because b and c have the same pointer, assigning 2.0 to c gives the same value to b. Therefore b prints out as 2.0, even though it was assigned 1.0.
If a pointee is declared as a character type, its Cray pointer is a Cray character pointer.
A Cray character pointer is a special data type that allows f90 to maintain character strings by keeping track of the following:
Byte address of the first character of the string
Length
Offset
An assignment to a Cray character pointer alters all three. That is, when you change what it points to, all three change.
For a pointee that has been declared with an assumed length character type, the Cray pointer declaration statement declares the pointer to be a Cray character pointer.
Before the Cray pointer declaration statement, declare the pointee as a character type with an assumed length.
Declare a Cray pointer to that pointee.
Assign a value to the Cray character pointer.
You can use functions CLOC or FCD, both nonstandard intrinsics.
Example: Declare Ccp to be a Cray character pointer and use CLOC to make it point to character string s.
CHARACTER*(*) a POINTER ( Ccp, a ) CHARACTER*80 :: s = "abcdefgskooterwxyz" Ccp = CLOC( s )
You can do the following operations with Cray character pointers:
Ccp1 + i |
Ccp1 - i |
i + Ccp1 |
Ccp1 = Ccp2 |
Ccp1 relational_operator Ccp2 |
where Ccp1 and Ccp2 are Cray character pointers and i is an integer.
All restrictions to Cray pointers also apply to Cray character pointers. In addition, the following apply:
A Cray character pointee cannot be an array.
In a relational operation, a Cray character pointer can be mixed with only another Cray character pointer--not with a Cray pointer, not with an integer.
A relational operation applies only to the character address and the bit offset; the length field is not involved.
Cray character pointers must not appear in EQUIVALENCE statements, or any storage association statements. (The size can vary with the platform.)
Cray character pointers are not optimized.
Code containing Cray character pointers is not parallelized.
A Cray character pointer in a list of an I/O statement is treated as an integer.
f90 supports some intrinsic procedures which are extensions beyond the standard.
Table C-4 Nonstandard Intrinsics
|
| Type |
|
|
|
Name |
Definition |
Function |
Arguments |
Arguments |
Notes |
CLOC |
Get Fortran character descriptor (FCD) |
Cray character pointer |
character | ([C=]c) |
NP, I |
COT |
Cotangent |
real |
real | ([X=]x) |
P, E |
DDIM |
Positive difference |
double precision |
double precision | ([X=]x,[Y=]y) |
P, E |
FCD |
Create Cray character pointer in Fortran character descriptor (FCD) format |
Cray pointer |
i: integer or Cray pointer j: integer |
([I=]i,[J=]j) i: word address of first character j: character length |
NP, I |
LEADZ |
Get the number of leading 0 bits |
integer |
Boolean, integer, real, or pointer | ([I=]i) |
NP, I |
POPCNT |
Get the number of set bits |
integer |
Boolean, integer, real, or pointer | ([I=]i) |
NP, I |
POPPAR |
Calculate bit population parity |
integer |
Boolean, integer, real, or pointer | ([X=]x) |
NP, I |
Notes on the above table: |
|
P |
The name can be passed as an argument. |
NP |
The name cannot be passed as an argument. |
E |
External code for the intrinsic is called at run time. |
I |
f90 generates inline code for the intrinsic procedure. |
A compiler directive directs the compiler to do some special action. Directives are also called pragmas.
A compiler directive is inserted into the source program as one or more lines of text. Each line looks like a comment, but has additional characters that identify it as more than a comment for this compiler. For most other compilers, it is treated as a comment, so there is some code portability.
Sun-style directives are the default with f90 (and f77). To switch to Cray-style directives, use the -mp=cray compiler command-line flag.
General directives have the following syntax.
!DIR$ d1, d2, ...
A general directive line is defined as follows.
Spaces before, after, or within a directive are ignored.
Letters of a directive line can be in uppercase, lowercase, or mixed.
The form varies for fixed-form and free-form source as follows.
Put CDIR$ or !DIR$ in columns 1 through 5.
Directives are listed in columns 7 and beyond.
Columns beyond 72 are ignored.
An initial directive line has a blank in column 6.
A continuation directive line has a nonblank in column 6.
Put !DIR$ followed by a space anywhere in the line. The !DIR$ characters are the first nonblank characters in the line (actually, non-whitespace).
Directives are listed after the space.
An initial directive line has a blank, tab, or newline in the position immediately after the !DIR$.
A continuation directive line has a character other than a blank, tab, or newline in the position immediately after the !DIR$.
Thus, !DIR$ in columns 1 through 5 works for both free-form source and fixed-form source.
These directives specify the source form of lines following the directive line.
They apply to the rest of the file in which they appear, or until the next FREE or FIXED directive is encountered.
They allow you to switch source forms within a source file.
They allow you to switch source forms for an INCLUDE file. You insert the directive at the start of the INCLUDE file. After the INCLUDE file has been processed, the source form reverts back to the form being used prior to processing the INCLUDE file.
The FREE/FIXED directives:
Each must appear alone on a compiler directive line (not continued).
Each can appear anywhere in your source code. Other directives must appear within the program unit they affect.
!DIR$ FREE DO i = 1, n a(i) = b(i) * c(i) END DO
A parallelization directive is a special comment that directs the compiler to attempt to parallelize the next DO loop. Currently there is only one parallel directive, DOALL.
The DOALL directive tells the compiler to parallelize the next loop it finds, if possible.
Parallel directives have the following syntax.
!MIC$ DOALL [general parameters] [scheduling parameter]
A parallelization directive line is defined as follows.
A parallel directive starts with the CMIC$ or !MIC$, followed by:
A space
A directive
For some directives, one or more parameters
Spaces before, after, or within a directive are ignored.
Letters of a parallelization directive line can be in uppercase, lowercase, or mixed.
The form varies for fixed-form and free-form source as follows.
Put CMIC$ or !MIC$ in columns 1 through 5.
Directives are listed in columns 7 and beyond.
Columns beyond 72 are ignored.
An initial directive line has a blank in column 6.
A continuation directive line has a nonblank in column 6.
Put !MIC$ followed by a space anywhere in the line. The !MIC$ characters are the first nonblank characters in the line (actually, non-whitespace).
Directives are listed after the space.
An initial directive line has a blank, tab, or newline in the position immediately after the !MIC$.
A continuation directive line has a character other than a blank, tab, or newline in the position immediately after the !MIC$.
Thus, !MIC$ in columns 1 through 5 works for both free and fixed.
Example: Directive with continuation lines (DOALL directive and parameters.)
C$PAR DOALL !MIC$& SHARED( a, b, c, n ) !MIC$& PRIVATE( i ) DO i = 1, n a(i) = b(i) * c(i) END DO
Example: Same directive and parameters, with no continuation lines.
C$PAR DOALL SHARED( a, b, c, n ) PRIVATE( i ) DO i = 1, n a(i) = b(i) * c(i) END DO
Standard-conforming FORTRAN 77 source code is compatible with Sun Fortran 90. Use of non-standard extensions, such as VMS Fortran features, are not compatible and may not compile with Sun Fortran 90.
Both f77 and f90 treat all source lines as if they were lowercase (except in quoted character strings. However, unlike f77, f90 has no -U option to force the compiler to be sensitive to both upper and lower case. This may present a problem when mixing f77 and f90 compiled routines. Since a routine compiled by f90 will treat CALL XyZ the same as CALL XYz, and treat them both as if they were CALL xyz, care must be taken to rearrange the way these calls are made. A similar situation will exist when trying to define entry points in f90 compiled routines that are differentiated by case. The clue to potential problems would be the need to use -U with f77.
To mix f77 and f90 object binaries, link with f90 and the f77 compatibility library, libf77compat, and not with libF77. For example, perform the link step with
f90 ..files.. -lf77compat
even if the main program is an f77 program.
Example: f90 main and f77 subroutine.
demo% cat m.f90 CHARACTER*74 :: c = 'This is a test.' CALL echo1( c ) END demo$ cat s.f SUBROUTINE echo1( a ) CHARACTER*74 a PRINT*, a RETURN END demo% f77 -c -silent s.f demo% f90 m.f90 s.o -lf77compat demo% a.out This is a test. demo%
The FORTRAN 77 library is generally compatible with f90.
Example: f90 main calls a routine from the FORTRAN 77 library.
demo% cat tdtime.f90 REAL e, dtime, t(2) e = dtime( t ) DO i = 1, 100000 as = as + cos(sqrt(float(i))) END DO e = dtime( t ) PRINT *, 'elapsed:', e, ', user:', t(1), ', sys:', t(2) END demo% f90 tdtime.f90 demo% a.out elapsed: 0.14 , user: 0.14 , sys: 0.0E+0 demo%
See dtime(3F).
f77 and f90 are generally I/O compatible for binary I/O, since f90 links to the f77 compatibility library.
Such compatibility includes the following two situations:
In the same program, you can write some records in f90, then read them in f77.
An f90 program can write a file. Then an f77 program can read it.
The numbers read back in may or may not equal the numbers written out.
Unformatted
The numbers read back in do equal the numbers written out.
Floating-point formatted
The numbers read back in can be different from the numbers written out. This is caused by slightly different base conversion routines, or by different conventions for uppercase/lowercase, spaces, plus or minus signs, and so forth.
Examples: 1.0e12, 1.0E12, 1.0E+12
List-directed
The numbers read back in can be different from the numbers written out. This can be caused by various layout conventions with commas, spaces, zeros, repeat factors, and so forth.
Example: '0.0' as compared to '.0'
Example: ' 7' as compared to '7'
Example: '3, 4, 5' as compared to '3 4 5'
Example: '3*0' as compared to '0 0 0'
The above results are from: integer::v(3)=(/0,0,0/); print *,v
Example: '0.333333343' as compared to '0.333333'
The above results are from PRINT *, 1.0/3.0
The Fortran 90 standard supports the following new intrinsic functions that FORTRAN 77 does not have.
If you use one of these names in your program, you must add an EXTERNAL statement to make f90 use your function rather than the intrinsic one.
Fortran 90 intrinsics:
"ADJUSTL,ADJUSTR,ALL,ALLOCATED,ANY,BIT_SIZE,COUNT,CSHIFT, DIGITS,DOT_PRODUCT,EOSHIFT,EPSILON,EXPONENT,HUGE,KIND, LBOUND,LEN_TRIM,MATMUL,MAXEXPONENT,MAXLOC,MAXVAL,MERGE, MINEXPONENT,MINLOC,MINVAL,NEAREST,PACK,PRECISION,PRESENT, PRODUCT,RADIX,RANGE,REPEAT,RESHAPE,RRSPACING,SCALE,SCAN, SELECTED_INT_KIND,SELECTED_REAL_KIND,SET_EXPONENT,SHAPE, SIZE,SPACING,SPREAD,SUM,TINY,TRANSFER,TRANSPOSE,UBOUND, UNPACK,VERIFY"
Future releases of f90 are intended to be source code compatible with this release.
Module information files generated by this release of f90 are not guaranteed to be compatible with future releases.
On Solaris systems, routines written in C can be combined with Fortran programs, since these languages have common calling conventions.
Compiling a file containing a Fortran 90 MODULE generates a module file (.mod file) for every MODULE encountered in the source. The file name is derived from the name of the MODULE; file xyz.mod (all lowercase) will be created for MODULE xyz.
By default, such files are usually sought in the current working directory. The -Mdir option allows you to tell f90 to seek them in an additional location.
The .mod files cannot be stored into an archive file, or concatenated into a single file.