2.26 Unifying Precision

The precision unifier standardises floating-point and complex variable declarations, floating-point and complex literal constants, and some specific (non-generic) intrinsic procedures in a set of Fortran source files in order to unify the precision of these entities.

Standardisation to quadruple precision is only available on machines for which quadruple-precision floating-point arithmetic is available.

The tool attempts to make a standardising precision parameter accessible in program units (and interface blocks) via a use statement. You can control the form of this statement: the -pp_name= option controls the name of the precision parameter, and the -pp_module= option supplies the name of its host module (which is known as the ‘precision module’). The default form for the use statement (when no options are specified) is USE WORKING_PRECISION, ONLY: WP.

The -precision= option (whose default value is Double) can be supplied to set the desired unifying precision. The tool will use this setting when performing a number of checks of the validity of the standardisation process on the input files.

The precision module can be created by the tool, but otherwise does not itself undergo precision unification. A warning is issued if the tool encounters this module. A message is also emitted if no definition for the precision parameter is found in the module, or otherwise if the defined precision parameter specifies a different kind to the desired precision as provided or implied by the -precision= option.

The tool searches each program unit and interface block in the input source and determines whether the precision parameter is already accessible. If it is not, then a use statement, in the form given above, is inserted in the last allowable position for its statement type. For an internal or module procedure this statement is placed in the host. If the precision parameter is already declared in the form INTEGER, PARAMETER :: wp = constant_expression, then this declaration is deleted and a new use statement added, as previously described. (This PARAMETER form of statement is only recognised as declaring the precision parameter if it precedes all declarations of floating-point or complex entities in the scoping unit.) Any other form of definition or import of the precision parameter will not be modified, and the tool issues a warning that the standardised use statement could not be inserted.

Type declarations for floating-point and complex entities are standardised to include the precision parameter as kind parameter. Entities that are implicitly typed to be floating-point or complex are explicitly declared, in the same form. In the case when a function is defined with a floating-point or complex type specification on the function statement, this specification is deleted and a distinct type declaration statement for the function result is inserted into the function's declaration section.

Floating-point and complex literal constants are standardised to use the precision parameter as their kind.

The option -pu_floats= controls the extent of precision conversions that are applied. The default behaviour described above for floating-point and complex entities corresponds to -pu_floats=On. The value -pu_floats=Default_Kinds may be supplied in order to limit the precision unification only to entities having default kind; i.e., kind specifiers already given in type declarations or for literals will be preserved, even if they differ from the desired unifying precision. Modification of all floating-point and complex entities may be suppressed altogether via -pu_floats=Off.

The following specific procedure references are standardised to the generic replacement listed below:

Specific Generic Specific Generic Specific Generic
ALOG10 LOG10 DATAN ATAN DSINH SINH
ALOG LOG DBLE REAL DSIN SIN
AMAX0(...) REAL(MAX(...)) DCMPLX CMPLX DSQRT SQRT
AMAX1 MAX DCONJG CONJG DTANH TANH
AMIN0(...) REAL(MIN(...)) DCOS COS DTAN TAN
AMIN1 MIN DCOSH COSH FLOAT REAL
AMOD MOD DDIM DIM IABS ABS
CABS ABS DEXP EXP IDIM DIM
CCOS COS DIMAG AIMAG IDINT INT
CDABS ABS DINT AINT IDNINT NINT
CEXP EXP DLOG10 LOG10 IFIX INT
CLOG LOG DLOG LOG ISIGN SIGN
CSIN SIN DMAX1 MAX MAX0 MAX
CSQRT SQRT DMIN1 MIN MAX1(...) INT(MAX(...))
DABS ABS DMOD MOD MIN0 MIN
DACOS ACOS DNINT ANINT MIN1(...) INT(MIN(...))
DASIN ASIN DREAL REAL SNGL REAL
DATAN2 ATAN2 DSIGN SIGN

(See also the description of -dcfuns.)

Furthermore, DBLE is converted to REAL. Following that, the KIND= argument is added to calls to REAL and CMPLX, when appropriate.

In cases where unifying the precision of the input source may lead in the generated output to undesirable side effects, or even invalid Fortran, the tool will attempt to issue a warning alerting you to the possibility. Here is a non-exhaustive list of situations where it may be inappropriate to apply this tool.

  1. Your source intentionally uses a mix of floating-point and complex precisions and you are running the tool in (the default) mode -pu_floats=On.
  2. You are employing Fortran language features for generic programming (such as generic interface blocks or parameterised derived types).
  3. You have floating-point or complex data in EQUIVALENCE statements or in references to the TRANSFER intrinsic.
  4. You have explicitly-typed intrinsic functions, or are passing intrinsic functions as procedure arguments.
  5. You are using the DPROD intrinsic (perhaps as a means of performing higher- (double-) precision computations in a single-precision program unit).
  6. You are mixing Fortran and non-Fortran code.

For procedures spread across several files clearly it is desirable to make sure this tool is applied to all files consistently. This will ensure, for example, that procedure references and the corresponding procedure definitions do not become inconsistent with respect to the type standardisation.

The precision unifier understands the following compiler options with the same meaning: -132, -abi, -dcfuns, -double, -dryrun, -dusty, -encoding, -english, -f2003, -f2008, -f95, -fixed, -free, -help, -I, -i8, -indirect, -info, -kind, -max_parameter_size, -maxcontin, -mismatch, -mismatch_all, -nihongo, -nocheck_modtime, -nomod, -noqueue, -o, -openmp, -Qpath, -r8, -strict95, -tempdir, -thread_safe, -u, -u=sharing, -v, -V, -w and -xlicinfo.

Note that using the -double or -r8 option affects the meaning of the -precision= option; see the description of the latter, below.

The standardised output is written to the file specified by the -o option, or to the same filename with the extension replaced by ‘.f90_prs’ if no -o option is specified. The output file cannot have the same name as the input file.

The precision unifier understands all the enhanced polish options with the same meaning.

The following additional options control the operation of this tool:

-nocmt_generation
If creating the precision module, do not add a comment saying when it was generated.
-pp_create_module
Automatically create the precision module, in the file whose name is the name of the module, converted to lower case, with file type ‘.f90’; thus the default filename is working_precision.f90. If the file already exists it will not be overwritten by this option.

The created module will contain only the definition of the precision parameter, and unless the -nocmt_generation option is given, a comment identifying when the module was created.

-pp_name=X
Specifies the name of the precision parameter to use in the standardised output, which must be a legal identifier that does not conflict with existing names in the input source. The default is ‘WP’.
-pp_module=X
Specifies the name of the precision module from which the precision parameter is to be imported. This module name must be a legal identifier that does not conflict with existing names in the input source. The default is ‘WORKING_PRECISION’.
-pp_nocreate_module
Do not create the precision module. This is the default.
-precision=X
Specifies the desired target unifying precision in the output; X must be one of Half, Single (i.e., same precision as default REAL), Double (i.e., same precision as default DOUBLE PRECISION) or Quadruple. The default is -precision=Double.

Note that, since -double and -r8 double the size of default REAL (and possibly default DOUBLE PRECISION), specifying -double or -r8 will likewise modify the meaning of this -precision= option too.

-pu_floats=X
Controls the precision-unification mode for floating-point and complex entities; X must be one of Off, On or Default_Kinds. In the latter mode of operation already-kinded entities will not be modified. The default is -pu_floats=On.