# NAG Fortran Compiler Frequently Asked Questions

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. 22. When will Fortran NNNN feature XYZ be available?" Answer. 23. Do you have any performance tips? Answer. How can I use CDABS, DCMPLX, DCONJG, DIMAG and DREAL? 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) Release 6.1 of the NAG Fortran Compiler can perform these conversions for you using the integrated precision unifier tool (nagfor =unifyprecision -dcfuns your_file.f90 from the command line); the -dcfuns option is used to make the compiler recognise these functions. Are non-standard specific intrinsic functions such as CDEXP available? 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. Release 6.1 of the NAG Fortran Compiler can carry out some conversions of intrinsic functions from specific to generic form for you, using the integrated precision unifier tool (nagfor =unifyprecision your_file.f90 from the command line). Is there a DTIME or ETIME function? 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 Is there a FLUSH procedure? 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 Is there a GETENV procedure? 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 Is there a “SYSTEM” procedure? 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 Can I use ‘$’ in a format to suppress newline?

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
90000 Format('What is your name? ')
Print *, 'Hello ', Trim(name)
End Program

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

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.

What does the warning “TAB format input” mean?
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).

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

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.

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

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.

What does “Buffer overflow on output” mean?

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.

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

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.

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

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.

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

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;
}

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

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

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

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

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)?

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.

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

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.

How should RANDOM_SEED be used to initialise the random number generator?
• 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


When will Fortran NNNN feature XYZ be available?

We are implementing features from all revisions of the Fortran standard as soon as possible, concentrating on the ones most frequently requested. If you are interested in feature XYZ please send an expression of your interest to support@nag.co.uk and it will be passed on to the compiler developers.

Do you have any performance tips?
Always try to use -O3 or -O4 (instead of just -O). This will lengthen compile time (sometimes substantially with -O4), but runtime performance is usually improved.

If you use assumed-shape arrays and you know that the actual arguments are always contiguous (i.e. you do not pass array slices using section notation), use -Oassumed=always_contig. With this option, a runtime error occurs if a non-contiguous actual argument is detected (so it is also useful for discovering whether you use such array sections).

If you are not 100% sure, but you think that this is true all or almost all of the time, use -Oassumed. With this option, non-contiguous actual arguments will be accepted though access to them will be slow.