Fortran Programming Guide HomeContentsPreviousNextIndex


Chapter 7

Porting

This chapter discusses the porting of programs from other dialects of Fortran to Sun compilers. VAX VMS Fortran programs compile almost exactly as is with Sun f77; this is discussed further in the chapter on VMS extensions in the FORTRAN 77 Language Reference Manual.


Note – Porting issues bear mostly upon Fortran 77 programs. The Sun WorkShop Fortran 95 compiler, f95, incorporates few nonstandard extensions, and these are described in the Fortran User's Guide.

Time and Date Functions

Library functions that return the time of day or elapsed CPU time vary from system to system.

The following time functions are not supported directly in the Sun Fortran libraries, but you can write subroutines to duplicate their functions:

The time functions supported in the Sun Fortran library are listed in the following table:

TABLE 7-1   Fortran Time Functions
Name Function Man Page
time Returns the number of seconds elapsed since January, 1, 1970 time(3F)
date Returns date as a character string date(3F)
fdate Returns the current time and date as a character string fdate(3F)
idate Returns the current month, day, and year in an integer array idate(3F)
itime Returns the current hour, minute, and second in an integer array itime(3F)
ctime Converts the time returned by the time function to a character string ctime(3F)
ltime Converts the time returned by the time function to the local time ltime(3F)
gmtime Converts the time returned by the time function to Greenwich time gmtime(3F)
etime Single processor: Returns elapsed user and system time for program execution
Multiple processors: Returns the wall clock time
etime(3F)
dtime Returns the elapsed user and system time since last call to dtime dtime(3F)
date_and_time Returns date and time in character and numeric form date_and_time(3F)


For details, see Fortran Library Reference Manual or the individual man pages for these functions.

The routines listed in the following table provide compatibility with VMS Fortran system routines idate and time. To use these routines, you must include the -lV77 option on the f77 command line, in which case you also get these VMS versions instead of the standard f77 versions.

TABLE 7-2   Summary: Nonstandard VMS Fortran System Routines
Name Definition Calling Sequence Argument Type
idate Date as day, month, year call idate( d, m, y ) integer
time Current time as hhmmss call time( t ) character*8



Note – The date(3F) routine and the VMS version of idate(3F) cannot be Year 2000 safe because they return 2-digit values for the year. Programs that compute time duration by subtracting dates returned by these routines will compute erroneous results after December 31, 1999. The Fortran 95 routine date_and_time(3F) is available for both FORTRAN 77 and Fortran 95 programs, and should be used instead. See the Fortran Library Reference Manual for details.

The error condition subroutine errsns is not provided, because it is totally specific to the VMS operating system.

Here is a simple example of the use of these time functions (TestTim.f):

      subroutine startclock 
      common / myclock / mytime 
      integer mytime, time 
      mytime = time() 
      return 
      end 
      function wallclock 
      integer wallclock 
      common / myclock / mytime 
      integer mytime, time, newtime 
      newtime = time() 
      wallclock = newtime - mytime 
      mytime = newtime 
      return 
      end 
      integer wallclock, elapsed 
      character*24 greeting 
      real dtime, timediff, timearray(2) 
c      print a heading 
      call fdate( greeting ) 
      print*,  "      Hello, Time Now Is: ",  greeting 
      print*,      "See how long 'sleep 4' takes, in seconds" 
      call startclock 
      call system( 'sleep 4' ) 
      elapsed = wallclock() 
      print*, "Elapsed time for sleep 4 was: ", elapsed," seconds"
c      now test the cpu time for some trivial computing 
      timediff = dtime( timearray ) 
      q = 0.01 
      do 30 i = 1, 1000 
            q = atan( q ) 
30      continue 
      timediff = dtime( timearray ) 
      print*, "atan(q) 1000 times took: ", timediff ," seconds"
      end 

Running this program produces the following results:

demo% TimeTest
       Hello, Time Now Is: Mon Feb 12 11:53:54 1996
 See how long 'sleep 4' takes, in seconds
 Elapsed time for sleep 4 was:   5 seconds
 atan(q) 1000 times took:     2.26550E-03 seconds
demo%

Formats

Some f77 and f95 format edit descriptors can behave differently on other systems. Here are some format specifiers that f77 treats differently than some other implementations:

Carriage-Control

Fortran carriage-control grew out of the capabilities of the equipment used when Fortran was originally developed. For similar historical reasons, an operating system derived from the UNIX operating system, does not have Fortran carriage control, but you can simulate it in two ways.

Working With Files

Early Fortran systems did not use named files, but did provide a command line mechanism to equate actual file names with internal unit numbers. This facility can be emulated in a number of ways, including standard UNIX redirection.

Example: Redirecting stdin to redir.data (using csh(1)):

demo% cat redir.data           The data file
 9 9.9 
 
demo% cat redir.f             The source file
      read(*,*) i, z          The program reads standard input
      print *, i, z 
      stop 
      end 
 
demo% f77 -silent -o redir redir.f  The compilation step
demo% redir < redir.data            Run with redirection reads data file
  9 9.90000
demo%

Porting From Scientific Mainframes

If the application code was originally developed for 64-bit (or 60-bit) mainframes such as CRAY or CDC, you might want to compile these codes with the following options when porting to an UltraSPARC-II platform, for example:

-fast -xarch=v9a -xchip=ultra2 \ -xtypemap=real:64,double:64,integer:64

These options automatically promote all default REAL variables and constants to REAL*8, and COMPLEX to COMPLEX*16. Only undeclared variables or variables declared as simply REAL or COMPLEX are promoted; variables declared explicitly (for example, REAL*4) are not promoted. All single-precision REAL constants are also promoted to REAL*8. (Set -xarch and -xchip appropriately for the target platform.) To also promote default DOUBLE PRECISION data to REAL*16, change the double:64 to double:128 in the -xtypemap example.

The -xtypemap option, is preferred over -dbl and -r8 and -i2. See the Fortran User's Guide and the f77(1) or f95(1) man pages for details.

To further recreate the original mainframe environment, it is probably preferable to stop on overflows, division by zero, and invalid operations. Compile the main program with -ftrap=common to ensure this.

Data Representation

The FORTRAN 77 Language Reference Manual, Fortran User's Guide, and the Sun Numerical Computation Guide discuss in detail the hardware representation of data objects in Fortran. Differences between data representations across systems and hardware platforms usually generate the most significant portability problems.

The following issues should be noted:

Hollerith Data

Many "dusty-deck" Fortran applications store Hollerith ASCII data into numerical data objects. With the 1977 Fortran standard (and Fortran 95), the CHARACTER data type was provided for this purpose and its use is recommended. You can still initialize variables with the older Fortran Hollerith (nH) feature, but this is not standard practice. The following table indicates the maximum number of characters that will fit into certain data types. (In this table, boldfaced data types indicate default types subject to promotion by the f77 command-line flags -dbl, -r8, or -xtypemap= ).

TABLE 7-3   f77: Maximum Characters in Data Types  

Maximum Number of Standard ASCII Characters
Data Type No -i2, -i4,
-r8, -dbl
-i2 -i4 -r8 -dbl
BYTE
1 1 1 1 1
COMPLEX
8 8 8 16 16
COMPLEX*16
16 16 16 16 16
COMPLEX*32
32 32 32 32 32
DOUBLE COMPLEX
16 16 16 32 32
DOUBLE PRECISION
8 8 8 16 16
INTEGER
4 2 4 4 8
INTEGER*2
2 2 2 2 2
INTEGER*4
4 4 4 4 4
INTEGER*8
8 8 8 8 8
LOGICAL
4 2 4 4 8
LOGICAL*1
1 1 1 1 1
LOGICAL*2
2 2 2 2 2
LOGICAL*4
4 4 4 4 4
LOGICAL*8
8 8 8 8 8
REAL
4 4 4 8 8
REAL*4
4 4 4 4 4
REAL*8
8 8 8 8 8
REAL*16
16 16 16 16 16


When storing standard ASCII characters with normal Fortran:

The storage is allocated with both options, but it is unavailable in normal Fortran with -r8.

Options -i2, -r8, and -dbl are now considered obsolete; use -xtypemap instead.

Example: Initialize variables with Hollerith:

demo% cat FourA8.f
      double complex x(2) 
      data x /16Habcdefghijklmnop, 16Hqrstuvwxyz012345/ 
      write( 6, '(4A8, "!")' ) x 
      end 
 
demo% f77 -silent -o FourA8 FourA8.f
demo% FourA8
abcdefghijklmnopqrstuvwxyz012345!
demo% 

If you pass Hollerith constants as arguments, or if you use them in expressions or comparisons, they are interpreted as character-type expressions.

If needed, you can initialize a data item of a compatible type with a Hollerith and then pass it to other routines.

Example:

        program respond
        integer yes, no
        integer ask
        data yes, no / 3hyes, 2hno /
 
        if ( ask() .eq. yes ) then
            print *, 'You may proceed!'
        else
            print *, 'Request Rejected!'
        endif
        end
 
        integer function ask()
        double precision solaris, response
        integer yes, no
        data yes, no / 3hyes, 2hno /
        data solaris/ 7hSOLARIS/
10      format( "What system? ", $ )
20      format( a8 )
 
        write( 6, 10 )
        read ( 5, 20 ) response
        ask = no
        if ( response .eq. solaris ) ask = yes
        return
        end

Nonstandard Coding Practices

As a general rule, porting an application program from one system and compiler to another can be made easier by eliminating any nonstandard coding. Optimizations or work-arounds that were successful on one system might only obscure and confuse compilers on other systems. In particular, optimized hand-tuning for one particular architecture can cause degradations in performance elsewhere. This is discussed later in the chapters on performance and tuning. However, the following issues are worth considering with regards to porting in general.

Uninitialized Variables

Some systems automatically initialize local and COMMON variables to zero or some "not-a-number" (NaN) value. However, there is no standard practice, and programs should not make assumptions regarding the initial value of any variable. To assure maximum portability, a program should initialize all variables.

Aliasing Across Calls

Aliasing occurs when the same storage address is referenced by more than one name. This happens when actual arguments to a subprogram overlap between themselves or between COMMON variables within the subprogram. For example, arguments X and Z refer to the same storage locations, as do B and H:

  COMMON /INS/B(100)
  REAL S(100), T(100)
  ...
  CALL SUB(S,T,S,B,100)
  ...
  SUBROUTINE SUB(X,Y,Z,H,N)
  REAL X(N),Y(N),Z(N),H(N)
  COMMON /INS/B(100)
  ...

Avoid aliasing in this manner in all portable code. The results on some systems and with higher optimization levels could be unpredictable.

Obscure Optimizations

Legacy codes may contain source-code restructurings of ordinary computational DO loops intended to cause older vectorizing compilers to generate optimal code for a particular architecture. In most cases, these restructurings are no longer needed and may degrade the portability of a program. Two common restructurings are strip-mining and loop unrolling.

Strip-Mining

Fixed-length vector registers on some architectures led programmers to manually "strip-mine" the array computations in a loop into segments:

  REAL TX(0:63)
  ...
  DO IOUTER = 1,NX,64
     DO IINNER = 0,63
        TX(IINNER) = AX(IOUTER+IINNER) * BX(IOUTER+IINNER)/2.
        QX(IOUTER+IINNER) = TX(IINNER)**2
     END DO
  END DO

Strip-mining is no longer appropriate with modern compilers; the loop can be written much less obscurely as:

  DO IX = 1,N
    TX = AX(I)*BX(I)/2.
    QX(I) = TX**2
  END DO

Loop Unrolling

Unrolling loops by hand was a typical source-code optimization technique before compilers were available that could perform this restructuring automatically. A loop written as:

  DO       K = 1, N-5, 6
     DO    J = 1, N
        DO I = 1,N
           A(I,J) = A(I,J) + B(I,K  ) * C(K  ,J)
 *                         + B(I,K+1) * C(K+1,J)
 *                         + B(I,K+2) * C(K+2,J)
 *                         + B(I,K+3) * C(K+3,J)
 *                         + B(I,K+4) * C(K+4,J)
 *                         + B(I,K+5) * C(K+5,J)
        END DO
     END DO
  END DO
  DO       KK = K,N
     DO    J =1,N
        DO I =1,N
           A(I,J) = A(I,J) + B(I,KK) * C(KK,J)
        END DO
     END DO
  END DO

should be rewritten the way it was originally intended:

  DO       K = 1,N
     DO    J = 1,N
        DO I = 1,N
           A(I,J) = A(I,J) + B(I,K) * C(K,J)
        END DO
     END DO
  END DO

Troubleshooting

Here are a few suggestions for what to try when programs ported to Sun Fortran do not run as expected.

Results Are Close, but Not Close Enough

Try the following:

VAX math is not as good as IEEE math, and even different IEEE processors may differ. This is especially true if the mathematics involves many trigonometric functions. These functions are much more complicated than one might think, and the standard defines only the basic arithmetic functions. There can be subtle differences, even between IEEE machines. Review the Floating-Point Arithmetic chapter in this Guide.
The output is:

99,999,990 x 10^29 = 0.99999993E+37 = 7CF0BDC1
99,999,996 x 10^29 = 0.99999993E+37 = 7CF0BDC1

In this example, the difference is 6 x 1029. The reason for this indistinguishable, wide gap is that in IEEE single-precision arithmetic, you are guaranteed only six decimal digits for any one decimal-to-binary conversion. You may be able to convert seven or eight digits correctly, but it depends on the number.

Program Fails Without Warning

If the program fails without warning and runs different lengths of time between failures, then:


Sun Microsystems, Inc.
Copyright information. All rights reserved.
Feedback
Library   |   Contents   |   Previous   |   Next   |   Index