NAG Fortran Compiler FAQ

  1. How can I use CDABS, DCMPLX, DCONJG, DIMAG and DREAL? Answer.
  2. Are non-standard specific intrinsic functions such as CDEXP available? Answer.
  3. Is there a DTIME or ETIME function? Answer.
  4. Is there a FLUSH procedure? Answer.
  5. Is there a GETENV procedure? Answer.
  6. Is there a SYSTEM procedure? Answer.
  7. Can I use ‘$’ in a format to suppress newline? Answer.
  8. How can I compile a very old (Fortran 66/77) program without getting errors? Answer.
  9. What does the warning “TAB format input” mean? Answer.
  10. Why does the message “Byte count on numeric data type” appear? Answer.
  11. Why do I get the message “KIND value does not specify a valid representation method” with the NAG compiler? Answer.
  12. What does “Buffer overflow on output” mean? Answer.
  13. Why do I get the message “Variable X size of N bytes is too big”? Answer.
  14. How can I control the maximum size of a named constant (PARAMETER)? Answer.
  15. When doing mixed-language programming, what are the functions f90_init and f90_io_finish? Answer.
  16. On program termination, the warning “Floating underflow occurred”; how can I find out where this is happening? Answer.
  17. On program termination, the warning “Floating underflow occurred”; how can I stop this warning from appearing? Answer.
  18. How can I read unformatted files written on a system with a different file format (e.g. endianness)? Answer.
  19. How can I write unformatted files so they can be read on a system with a different file format (e.g. endianness)? Answer.
  20. Is it possible to redistribute applications built with the NAG Fortran Compiler? Answer.
  21. How should RANDOM_SEED be used to initialise the random number generator? Answer.

Question: How can I use CDABS, DCMPLX, DCONJG, DIMAG and DREAL?
Answer: These are not standard Fortran intrinsic functions, though they are a common extension. We recommend that they be converted to standard Fortran using the following table.
Specific Equivalent Modern Fortran Generic Intrinsic Function
CDABS(A) Abs(a)
DCMPLX(X,Y) Cmplx(x,y,Kind=Kind(0d0))
DCONJG(Z) Conjg(z)
DIMAG(Z) Aimag(z)
DREAL(Z) Real(z)

Alternatively, the ‘-dcfuns’ option can be used to make the compiler recognise these functions.


Question: Are non-standard specific intrinsic functions such as CDEXP available?
Answer:

No. These functions have never been part of any Fortran standard, and there is not universal agreement on their spelling.

However, they are never needed: just use the standard generic intrinsic functions: ABS, ACOS, ASIN, ATAN, ATAN2, CONJG, COS, COSH, DIM, EXP, LOG, LOG10, MAX, MIN, SIGN, SIN, SINH, SQRT, TAN and TANH can all be applied to any precision Real (and where appropriate, Complex) data.

If you have a program that uses a specific intrinsic (non-standard or standard) that consists of a prefix in front of one of the functions listed above, removing the prefix (usually C, CD, CQ, D, Q or Z) is nearly always the right thing to do; for example, references to an intrinsic CEXP, DEXP, CDEXP, CQEXP, DCEXP, QEXP, ZEXP can all safely be replaced by EXP.

For a few functions, the rule is slightly different: xINT and xNINT, where x is one of the prefixes listed above, should be changed to AINT or ANINT respectively.


Question: Is there a DTIME or ETIME function?
Answer: No.

These functions are not standard Fortran; their functionality is provided by the standard Fortran intrinsic subroutines CPU_TIME and SYSTEM_CLOCK. If you have a package that wants to use the DTIME and/or ETIME procedures, you can add one or two of the following examples to your code. The first example provides DTIME and ETIME> written entirely in standard Fortran 95 (and thus will work on any Fortran 95 compiler); the second provides DTIME and ETIME using the NAG Fortran Compiler interface to Posix.

NOTE: By design, the DTIME and ETIME functions are not and cannot be thread-safe. If your code might be executed in a multi-threaded environment, you should use SYSTEM_CLOCK to measure elapsed time.

 

! DTIME in standard Fortran.
Real Function dtime(time)
  Real time(2)
  Double Precision,Save :: last_time = 0
  Double Precision this_time
  Intrinsic Cpu_Time
  Call Cpu_Time(this_time)
  time(1) = this_time - last_time
  time(2) = 0
  dtime = time(1)
  last_time = this_time
End Function
! DTIME via NAG Fortran Compiler Posix module.
Real Function dtime(time)
  Use F90_Unix_Env,Only:tms,times
  Real time(2)
  Type(tms),Save :: lastbuf
  Logical :: start = .True.
  Type(tms) buffer
  Integer junk
  junk = times(buffer)
  If (start) Then
    lastbuf%utime = 0
    lastbuf%stime = 0
    start = .false.
  End If
  time(1) = buffer%utime - lastbuf%utime
  time(2) = buffer%stime - lastbuf%stime
  dtime = time(1) + time(2)
  lastbuf = buffer
End Function
! ETIME in standard Fortran.
Real Function etime(time)
  Real time(2)
  Call Cpu_Time(etime)
  time(1) = etime
  time(2) = 0
End Function
! ETIME via NAG Fortran Compiler Posix module.
Real Function etime(time)
  Use F90_Unix_Env,Only:tms,times
  Real time(2)
  Type(tms) buffer
  Integer junk
  junk = times(buffer)
  time(1) = buffer%utime
  time(2) = buffer%stime
  etime = buffer%utime + buffer%stime
End Function

Question: Is there a FLUSH procedure?
Answer:

Yes. Fortran 2003 standardized this facility as the FLUSH statement.

Here is a simple example showing how to use it.

Program slow_dots
!
! This program prints 10 dots, one per second, then finishes.
!
  Use Iso_Fortran_Env,Only:output_unit
  Implicit None
  Integer i
  Do i = 1,10
    Write(*,'(a)',Advance='No') '.'
    Call delay
    Flush(output_unit)
  End Do
  Print *,'Done.'
Contains
  Subroutine delay
    Integer per_second,start,now
    Intrinsic System_Clock
    Call System_Clock(Count=start,Count_Rate=per_second)
    If (start==-huge(start)) Stop 'No clock.'
    Do
      Call System_Clock(Count=now)
      If (now<start .Or. now>=start+per_second) Exit
    End Do
  End Subroutine
End Program

 


Question: Is there a GETENV procedure?
Answer: Yes. Fortran 2003 standardized this facility as the GET_ENVIRONMENT_VARIABLE intrinsic procedure.

Here is a simple example showing how to use it.

Program environment_example
!
! This program displays the values of the environment variables FRED and
USERNAME
! (if they exist).
!
  Implicit None
  Call show('FRED')
  Call show('USERNAME')
Contains
  Subroutine show(name)
    Character(*),Intent(In) :: name
    Character(:),Allocatable :: value
    Integer len,status
    Intrinsic Get_Environment_Variable
    Call Get_Environment_Variable(name,Status=status,Length=len)
    If (status==1) Then
      Print *,'Environment variable "',name,'" does not exist.'
    Else If (status/=0) Then
      Print *,'Unexpected error',status,'for environment variable "',name,'"'
    Else
      Allocate(Character(len) :: value)
      Call Get_Environment_Variable(name,Value=value)
      Print *,'The value of environment variable "',name,'" is "',value,'".'
    End If
  End Subroutine
End Program

 


Question: Is there a “SYSTEM” procedure?
Answer:

Yes. Fortran 2008 standardized this facility as the EXECUTE_COMMAND_LINE intrinsic procedure.

Here is a simple example showing how to use it.

Program execute_cmd_example
  Call execute_command_line('echo Hello World!')
End Program

Question: Can I use ‘$’ in a format to suppress newline?
Answer:

No, the NAG Fortran Compiler does not accept this extension.

This extension is completely obsolete with the introduction, by Fortran 90, of non-advancing input/output. Here is an example of how to produce a prompt with standard Fortran.

    Program prompting
      Character(80) name
      Write (*,90000,Advance='No')
90000 Format('What is your name? ')
      Read *, name
      Print *, 'Hello ', Trim(name)
    End Program

Question: How can I compile a very old (Fortran 66/77) program without getting errors?
Answer:

The NAG Fortran Compiler carries out a strict check for conformance to the Fortran standard and also carries out a large number of checks for obviously incorrect code. While this is the correct behaviour for a compiler when new code is being developed, it is sometimes necessary to reduce the stringency of error checking to allow older code written to lower standards to compile. There are a number of compiler options to compile such legacy code.

-dusty
Downgrades a number of common errors found in legacy code to warnings. Hence compilation can continue; these warnings can be suppressed by the ‘-w’ option. This option implies the ‘-mismatch_all’ option.
-mismatch
Downgrades errors resulting from mismatch in argument lists to warnings. Calls to routines in the same file must still be correct.
-mismatch_all
As ‘-mismatch’, but even incorrect calls to routines in the same file are accepted.

 


Question: What does the warning “TAB format input” mean?
Answer: TAB format is an extension to Fortran 77, and operates when TAB characters are found in fixed form source files. Because it is an extension, a warning message is produced. This format is a bit complicated, and not recommended for new programs (use free form source instead).

Question: Why does the message “Byte count on numeric data type” appear?
Answer:

This is an extension to Fortran 77 that was made obsolete by Fortran 90. Instead of specifying the number of bytes, Fortran 90 has kinds of each datatype, and intrinsic functions for choosing a kind based on the desired properties (SELECTED_INT_KIND and SELECTED_REAL_KIND). The NAG Fortran Compiler also provides a module, F90_KIND, which has named constants for convenient kind selection (the names for Integer and Real/Complex are also available from the standard intrinsic module ISO_FORTRAN_ENV). The equivalence between byte sizes and kinds using these names is as follows.

Type * Byte Size Type(Kind Name)
INTEGER*1 Integer(int8)
INTEGER*2 Integer(int16)
INTEGER*4 Integer(int32)
INTEGER*8 Integer(int64)
REAL*4 Real(real32)
REAL*8 Real(real64)
REAL*16 Real(real128)
COMPLEX*8 Complex(real32)
COMPLEX*16 Complex(real64)
COMPLEX*32 Complex(real128)

The kind of an integer or real constant is specified by appending an underscore and the kind value (or name); e.g. 120_int8 is an 8-bit integer constant, and 3.14159265358979323846264338327950288_real128 is a 128-bit real value.


Question: Why do I get the message “KIND value does not specify a valid representation method” with the NAG compiler?
Answer:

The interpretation of kind values depends on the compiler. There are at least two obvious methods: sequential (1 to N, where N is the number of kinds) and byte (use the number of bytes for Integer and Real type). The NAG Fortran Compiler (and some other compilers) by default uses sequential kind numbering, so single and double precision real are REAL(1) and REAL(2), not REAL(4) and REAL(8). The disadvantage of the so-called “byte” scheme is that for the Complex type, the setting is the number of bytes for each part, i.e. half the total, which can be confusing.

The compiler option ‘-kind=sequential’ (the default) or ‘-kind=byte’ selects the method.


Question: What does “Buffer overflow on output” mean?
Answer:

This means that your program attempted a sequential write, in a single record, with more bytes than will fit into the file buffer for that unit. For formatted input/output, please refer to the Compiler Manual for the current implementation limit; for unformatted input/output, the default is unlimited.

To change the buffer size you can use the RECL= specifier in the OPEN statement for the file you wish to write. For example:

Open(13,File="myfile",Form="Formatted",Recl=2048)
will establish a buffer size of 2048 bytes on unit 13.

 

Note that Fortran provides the IOLENGTH= specifier in the INQUIRE statement to discover the needed value for RECL= for an unformatted file. For example:

Inquire(Iolength=n) big_array
Open(13,File="dump",Form="Unformatted",Recl=N)
will establish a sufficiently large buffer for unit 13 to allow the entirety of big_array to be read or written in one input/output statement.

 

An unlimited buffer size can be established for formatted input/output by using the Fortran 2003 feature “stream access”; however, this will disable the BACKSPACE statement on that unit. For example,

Open(13,File="list",Form="Formatted",Access="Stream")
will open unit 13 for stream access, enabling formatting input/output of records of unlimited length, but disabling the ability to backspace the unit.

 


Question: Why do I get the message “Variable X size of N bytes is too big”?
Answer:

This means that your variable is larger than the maximum object size supported by the NAG Fortran Compiler's current mode.

Please refer to the Compiler's Manual for a list of its current implementation limits.


Question: How can I control the maximum size of a named constant (PARAMETER)?
Answer:

The maximum size of a named constant is controlled with the −max_parameter_size= option. This takes a limit in megabytes (MB); the default is −max_parameter_size=50.


Question: When doing mixed-language programming, what are the functions f90_init and f90_io_finish?
Answer:

These functions are needed when the main program is in C instead of Fortran. The f90_init function initialises the Fortran environment, including the floating-point status, command-line arguments, and input/output subsystem. The f90_io_finish function writes the contents of all the Fortran output buffers to their files, and closes all the Fortran files. The following example shows how to use these functions.

int main(int argc,char *argv[])
{
  f90_init(argc,argv);
  /* At this point Fortran routines can be safely called. */
  f90_io_finish();
  return 0;
}

Question: On program termination, the warning “Floating underflow occurred”; how can I find out where this is happening?
Answer:

Floating underflow is quite common in programs, and is rarely a problem. If it is a problem, you can set the IEEE halting mode for underflow to cause the program to stop when it happens; note that you should also set the “Traceback for runtime errors (−gline)” option so that the location will be reported.

The following program shows how to use IEEE halting mode to cause termination on underflow.

Program underflow_halt
  Use Ieee_Exceptions
  Implicit None
  Call Ieee_Set_Halting_Mode(Ieee_Underflow, .True.)
  Call make_underflow(0.5)
Contains
  Subroutine make_underflow(x)
    Real, Intent(In) :: x
    Real :: y
    Integer :: n
    y = x
    n = 1
    Do
      y = y**2
      If (y==0) Exit
      n = n + 1
      Print *, 'Step', n, 'value', y
    End Do
    Print *, 'Zero reached at step', n
  End Subroutine
End Program

Question: On program termination, the warning “Floating underflow occurred”; how can I stop this warning from appearing?
Answer:

The Floating underflow warning can be suppressed in two ways:

  • the underflow flag can be set to false before program termination;
  • the link-time option −no_underflow_warning can be used.

     

    The following program shows how to use IEEE halting mode to turn the underflow flag off prior to program termination.

    Program turn_underflow_flag_off
      Use Ieee_Exceptions
      Implicit None
      Call make_underflow(0.5)
      Call Ieee_Set_Flag(Ieee_Underflow, .False.)
    Contains
      Subroutine make_underflow(x)
        Real, Intent(In) :: x
        Real :: y
        Integer :: n
        y = x
        n = 1
        Do
          y = y**2
          If (y==0) Exit
          n = n + 1
          Print *, 'Step', n, 'value', y
        End Do
        Print *, 'Zero reached at step', n
      End Subroutine
    End Program

Question: How can I read unformatted files written on a system with a different file format (e.g. endianness)?
How can I write unformatted files so they can be read on a system with a different file format (e.g. endianness)?
Answer:

Unformatted file conversion is provided by three mechanisms:

  • the −convert= option;
  • the CONVERT= specifier on the OPEN statement;
  • the FORT_CONVERTn environment variable.

     

    Unformatted file conversion affects both reading and writing, so the same mechanism provides the answer for both questions.

    The most common conversion requirement is for big-endian files with all floating-point data in IEEE format; this is provided by the “−convert=big_ieee” option.

    For full details of the conversion mechanisms please refer to the Compiler Manual.


Question: Is it possible to redistribute applications built with the NAG Fortran Compiler?
Answer:

Yes, it is possible. The easiest way to do this is to link the NAG Fortran Compiler run time library statically using the −unsharedrts option.


Question: How should RANDOM_SEED be used to initialise the random number generator?
Answer:
  • RANDOM_SEED is not necessary to initialise the random number generator, provided you are happy to get a different sequence with each execution. When you use RANDOM_NUMBER the generator will be initialised automatically.

    Here is an example:

    Program unique_sequences
      Implicit None
      Print *,'First sequence'
      Call show_random(8)
      Print *,'Second (different) sequence'
      Call show_random(8)
    Contains
      Subroutine show_random(n)
        Integer,Intent(In) :: n
        Real x(n)
        Call Random_Number(x)
        Print 1,x
    1   Format(99F8.5)
      End Subroutine
    End Program
    
  • RANDOM_NUMBER is the Mersenne Twister; this generator has a large amount of state (630 32-bit integers) and incorrect initialisation can result in poor quality numbers being generated. Therefore it is recommended that RANDOM_SEED only be used to replay a previous sequence.

    Here is an example:

    Program sequence_restarting
      Implicit None
      Integer rsize
      Integer,Allocatable :: rseed(:)
      Call Random_Seed(Size=rsize) ! Get the size of the seed (630 for NAG).
      Allocate(rseed(rsize))       ! Allocate an array to save it.
      Call Random_Seed(Get=rseed)  ! Save it.
      Print *,'First sequence'
      Call show_random(8)
      Call Random_Seed(Put=rseed)  ! Restart the sequence at the saved state.
      Print *,'Second (restarted) sequence'
      Call show_random(8)
    Contains
      Subroutine show_random(n)
        Integer,Intent(In) :: n
        Real x(n)
        Call Random_Number(x)
        Print 1,x
    1   Format(99F8.5)
      End Subroutine
    End Program
    
  • In the case of wanting the same sequence with every execution, you can use RANDOM_SEED with your own seed data. The Mersenne Twister state is a random bit sequence and it should therefore have approximately equal numbers of zero and one bits. If you do not have 630 32-bit integers worth of random data, you should set the remaining elements of the seed array to zero so that the generator will know that these do not contain any useful entropy.

    Here is an example:

    Program repeatable_sequences
      Implicit None
      Integer rsize
      Integer,Allocatable :: rseed(:)
      Call Random_Seed(Size=rsize) ! Get the seed size.
      Allocate(rseed(rsize))       ! Allocate the seed.
      rseed(1) = Int(z'1f2d3b5a')  ! Assign the "random" values we have.
      rseed(2:) = 0                ! Set the rest to zero.
      Call Random_Seed(Put=rseed)  ! Initialise the generator.
      Print *,'First sequence (always the same)'
      Call show_random(8)
      Call Random_Seed(Put=rseed)  ! Re-initialise the generator.
      Print *,'Second sequence (also always the same)'
      Call show_random(8)
    Contains
      Subroutine show_random(n)
        Integer,Intent(In) :: n
        Real x(n)
        Call Random_Number(x)
        Print 1,x
    1   Format(99F8.5)
      End Subroutine
    End Program