1

I am using intel fortran 2016. I have defined some precision variables as follows:

 ! definition of single, double and quad precision
        integer, parameter :: SINGLE_PRECISION = selected_real_kind(6, 37)
        integer, parameter :: DOUBLE_PRECISION = selected_real_kind(15, 307) ! is used as standard precision
        integer, parameter :: QUAD_PRECISION = selected_real_kind(33, 4931)

        ! definition of variable precision for REAL, INTEGER
        integer, parameter :: REAL_TYPE = DOUBLE_PRECISION
        integer, parameter :: INTEGER_TYPE = 4

I would like to now use these to control the precision of a parameter that gets declared in a subroutine as follows:

  SUBROUTINE SKIP(IUNIT,NBYTS)

  IMPLICIT DOUBLE PRECISION (A-H,O-Z)
  Character c*1
  Parameter(n1 = 1024, nT1 = 8*n1)

I tried the following :

Parameter(INTEGER_TYPE)((n1 = 1024, nT1 = 8*n1)
Parameter(INTEGER_TYPE)((n1 = 1024, nT1 = 8*n1, kind = INTEGER_TYPE)

All to no avail. What is the proper way to define parameter precision in Fortran?

Thanks

user32882
  • 5,094
  • 5
  • 43
  • 82
  • 3
    If you are using modern Fortran with kinds, do not use implicit typing and parameter statements. Just define the type and the value of the parameter in one statement as shown in answers below (and the very same way you define your own kind parameters). And use IMPLICIT NONE, it will save you hours if not days of debugging. – Vladimir F Героям слава Mar 20 '18 at 11:17

3 Answers3

3

Note: this is essentially the same as Francescalus' answer, but with some extra fluf.

The issue at hand here is related to the IMPLICIT statement.

The Fortran standard makes the following statements :

5.5 IMPLICIT statement

  1. In a scoping unit, an IMPLICIT statement specifies a type, and possibly type parameters, for all implicitly typed data entities whose names begin with one of the letters specified in the statement. Alternatively, it may indicate that no implicit typing rules are to apply in a particular scoping unit.

  2. <snip>

  3. In each scoping unit, there is a mapping, which may be null, between each of the letters A, B, ..., Z and a type (and type parameters). An IMPLICIT statement specifies the mapping for the letters in its letter-spec-list. IMPLICIT NONE specifies the null mapping for all the letters. If a mapping is not specified for a letter, the default for a program unit or an interface body is default integer if the letter is I, J, ..., or N and default real otherwise, and the default for an internal or module procedure is the mapping in the host scoping unit.

So in short, by default everything is of type default REAL unless it starts with I,J,...,N, then it is of type default INTEGER.

In the example in the question, the variables n1 and nT1 are hence default INTEGER unless specified otherwise. Thus the following might be a solution :

subroutine skip(IUNIT,NBYTS)
   implicit double precision (A-H,O-Z)
   character c*1
   integer(kind=integer_kind), parameter :: n1 = 1024, nT1 = 8*n1
   ...
end subroutine skip

As a general remark on variable declaration I would like to make the following remarks:

  • use implicit none as default. It makes debugging easier
  • avoid star notation, it is not part of the standard for anything but characters, and for characters it is declared obsolescent.
  • make use of kind parameters declared in the intrinsic module iso_fortran_env
  • be aware that double precision does not necessarily mean "double precision" in the literal or IEEE sense of the word. It just means, twice the storage of a real and a higher precision than real. (a higher precision could be one-digit).
kvantour
  • 25,269
  • 4
  • 47
  • 72
1

You can define a parameter of a specific kind with

TYPE, PARAMETER :: name = value_kind

So to define, say, an integer n1 with kind INTEGER_TYPE you do

integer(kind=INTEGER_TYPE), parameter :: n1 = 1024_INTEGER_TYPE
janneb
  • 36,249
  • 2
  • 81
  • 97
1

You have an answer which gives the best way to specify the kind of a named constant. You can find much more detail around this question.

However, I'll add some detail about the parameter statement.

The parameter statement makes an object a named constant and specifies its value. It doesn't specify the type or kind of that object.

The example of the question uses implicit typing for n1 and nT1. These are implicitly default integer.

The implicit rule may be changed (I won't show how), but the type may also be given explicitly:

integer(INTEGER_TYPE) n1, nT1
parameter (n1=1024, nT1=8*n1)

Still, the form of the other answer is preferable. And, as noted there, the kind of the literal constants may also be given in the parameter statement if desired.

francescalus
  • 30,576
  • 16
  • 61
  • 96