56

I am having trouble understanding Fortran 90's kind parameter. As far as I can tell, it does not determine the precision (i.e., float or double) of a variable, nor does it determine the type of a variable.

So, what does it determine and what exactly is it for?

1
  • are you referring to Kind notation? Commented May 8, 2009 at 5:46

6 Answers 6

71

The KIND of a variable is an integer label which tells the compiler which of its supported kinds it should use.

Beware that although it is common for the KIND parameter to be the same as the number of bytes stored in a variable of that KIND, it is not required by the Fortran standard.

That is, on a lot of systems,

REAl(KIND=4) :: xs ! 4 byte ieee float REAl(KIND=8) :: xd ! 8 byte ieee float REAl(KIND=16) :: xq ! 16 byte ieee float 

but there may be compilers for example with:

REAL(KIND=1) :: XS ! 4 BYTE FLOAT REAL(KIND=2) :: XD ! 8 BYTE FLOAT REAL(KIND=3) :: XQ ! 16 BYTE FLOAT 

Similarly for integer and logical types.

(If I went digging, I could probably find examples. Search the usenet group comp.lang.fortran for kind to find examples. The most informed discussion of Fortran occurs there, with some highly experienced people contributing.)

So, if you can't count on a particular kind value giving you the same data representation on different platforms, what do you do? That's what the intrinsic functions SELECTED_REAL_KIND and SELECTED_INT_KIND are for. Basically, you tell the function what sort of numbers you need to be able to represent, and it will return the kind you need to use.

I usually use these kinds, as they usually give me 4 byte and 8 byte reals:

!--! specific precisions, usually same as real and double precision integer, parameter :: r6 = selected_real_kind(6) integer, parameter :: r15 = selected_real_kind(15) 

So I might subsequently declare a variable as:

real(kind=r15) :: xd 

Note that this may cause problems where you use mixed language programs, and you need to absolutely specify the number of bytes that variables occupy. If you need to make sure, there are enquiry intrinsics that will tell you about each kind, from which you can deduce the memory footprint of a variable, its precision, exponent range and so on. Or, you can revert to the non-standard but commonplace real*4, real*8 etc declaration style.

When you start with a new compiler, it's worth looking at the compiler specific kind values so you know what you're dealing with. Search the net for kindfinder.f90 for a handy program that will tell you about the kinds available for a compiler.

Sign up to request clarification or add additional context in comments.

6 Comments

Thanks for pointing out that KIND is not KIND=<number of bytes I want> - have you seen a modern compiler where this is the case? That kindfinder.f90 program is very cool.
A search of usenet turns up: salford f95 compiler uses kinds 1,2, and 3 to stand for 2- 4- and 8-byte variables; I saw a claim that g77 did the same before g95 and gfortran came along; and a report that the NAG fortran compiler had a compiler switch that allowed the selection between the (1,2,3,4) scheme and the (1,2,4,8) scheme. No doubt there are others. Yes, kindfinder is handy. You can use it to set up a site-specific module file that contains named parameters for the different kinds, so that your real programs aren't littered with nonportable magic numbers.
If you really want to specify types by their bytes of storage, Fortran 2003 has the ISO_C_Binding, which provides kind values corresponding to C types, some of which specify storage size. Fortran 2008 provides types in the ISO_FORTRAN_ENV module, such as the real32 kind value for 32 bits, real64 for 64 bits, etc. These have the advantage of being portable, at least as long as you have a Fortran 2003 or 2008 compiler. See the gfortran manual for the list of kinds in these two modules.
@Eular Late to this, but am currently getting acquainted to these, and I found this : fortranwiki.org/fortran/show/Real+precision Here in first block, a and b are declared using real(kind=dp) and real(dp) respectively, and it appears they both mean the same thing.
@ZeroTwo Yes, they do. Be careful with character kinds there the firstvnumber is the length. character(4) is the string of lenght 4. character(c_char) is the string of length c_char. character(kind=c_char) is a single character of length 1.
|
12

I suggest using the Fortran 2008 and later; INT8, INT16, INT32, INT64, REAL32, REAL64, REAL128. This is done by calling ISO_FORTRAN_ENV in Fortran 2003 and later. Kind parameters provides inconsistent way to ensure you always get the appropriate number of bit representation

6 Comments

int8 does (if an appropriate kind is available) specify a kind parameter. I suspect you mean that one should prefer this to an explicit number like, say int(kind=1)? [This latter would be bad practice regardless.] Perhaps you could clarify?
I concur with your comment @francescalus
@francescalus, would it not be useful to make this question a canonical question and have a single "community answer" which sums up all the entire story for various versions of fortran? Often I see code where I would like to refer to such a complete canonical answer. This is the best place here, but the information is completely spread out over different answers and various comments. (sorry this is the best way I figured out to reach you)
@kvantour, discussions of canonical questions (scope, desire, etc.) fit well on Meta SO. You'll likely get more than just my opinion there. That's if you think the question itself needs work: if you think an answer here solves the problem then there's little harm pulling everything together into a complete form.
-1. software.intel.com/content/www/us/en/develop/blogs/… -- TLDR: use SELECTED_REAL_KIND()
|
5

Just expanding the other (very good) answers, specially Andrej Panjkov's answer:

The KIND of a variable is an integer label which tells the compiler which of its supported kinds it should use.

Exactly. Even though, for all the numeric intrinsic types, the KIND parameter is used to specify the "model for the representation and behavior of numbers on a processor" (words from the Section 16.5 of the standard), that in practice means their bit model, that's not the only thing a KIND parameter may represent.

A KIND parameter for a type is any variation in its nature, model or behavior that is avaliable for the programmer to choose at compile time. For example, for the intrinsic character type, the kind parameter represents the character sets avaliable on the processor (ASCII, UCS-4,...).

You can even define your own model/behaviour variations on you defined Derived Types (from Fortran 2003 afterwards). You can create a Transform Matrix type and have a version with KIND=2 for 2D space (in which the underlying array would be 3x3) and KIND=3 for 3D space (with a 4x4 underlying array). Just remember that there is no automatic kind conversion for non-intrinsic types.

Comments

2

From the Portland Group Fortran Reference, the KIND parameter "specifies a precision for intrinsic data types." Thus, in the declaration

real(kind=4) :: float32 real(kind=8) :: float64 

the variable float64 declared as an 8-byte real (the old Fortran DOUBLE PRECISION) and the variable float32 is declared as a 4-byte real (the old Fortran REAL).

This is nice because it allows you to fix the precision for your variables independent of the compiler and machine you are running on. If you are running a computation that requires more precision that the traditional IEEE-single-precision real (which, if you're taking a numerical analysis class, is very probable), but declare your variable as real :: myVar, you'll be fine if the compiler is set to default all real values to double-precision, but changing the compiler options or moving your code to a different machine with different default sizes for real and integer variables will lead to some possibly nasty surprises (e.g. your iterative matrix solver blows up).

Fortran also includes some functions that will help pick a KIND parameter to be what you need - SELECTED_INT_KIND and SELECTED_REAL_KIND - but if you are just learning I wouldn't worry about those at this point.

Since you mentioned that you're learning Fortran as part of a class, you should also see this question on Fortran resources and maybe look at the reference manuals from the compiler suite that you are using (e.g. Portland Group or Intel) - these are usually freely available.

1 Comment

Nope, this is not portable. Don't recommend it to beginners please.
-2

One of the uses of kind could be to make sure that for different machine or OS, they truly use the same precision and the result should be the same. So the code is portable. E.g.,

integer, parameter :: r8 = selected_real_kind(15,9) real(kind=r8) :: a 

Now this variable a is always r8 type, which is a true "double precision" (so it occupies 64 bits of memory on the electronic computer), no matter what machine/OS the code is running on.

Also, therefore you can write things like,

a = 1.0_r8 

and this _r8 make sure that 1.0 is converted to r8 type.

20 Comments

Why is a guaranteed to be an 8-byte real for every processor?
This is just wrong. The different machine might use some non IEEE floating point types. Alas, the 8-byte float may not even exist on such a machine and still the machine could have a conforming Fortran 90 compiler.
selected_real_kind is simply not about storage size at all. It does not really matter what you do in your HPC. It is about numerical precision. It says how big and precise numbers can be. I repeat, a conforming Fortran processor can exist on a machine that does not even have to have any 8-byte type. Those that do have it will have real64 defined in iso_fortran_env and that is the true way to define a true 8-byte real. And if an IEEE conforming 8-type is available, you can use the ieee_selected_real_kind, where the correspondende between numerical precision and storage size more certain.
I am not saying that what you do will not work for you on a typical IEEE conforming machine in this day and age. I am saying that the claim "which is real 8 (means uses 8 Bytes) type no matter what machine/OS it is running on." is incorrect from a language lawyer point of view. It also does not guarantee that the results will be the same.
Using selected_real_kind in this answer you have asked for a minimal decimal precision and range. You haven't asked for a storage size, radix, IEEE conformance or exact range and precision. There is nothing in the Fortran language that says you will get an 8-byte real with this kind parameter.
|
-8

To summarize other answers: the kind parameter specifies storage size (and thus indirectly, the precision) for intrinsic data types, such as integer and real.

However, the recommended way now is NOT to specify the kind value of variables in source code, instead, use compiler options to specify the precision we want. For example, we write in the code: real :: abc and then compile the code by using the compiling option -fdefault-real-8 (for gfortran) to specify a 8 byte float number. For ifort, the corresponding option is -r8.

Update:

It seems Fortran experts here strongly object to the recommended way stated above. In spite of this, I still think the above way is a good practice that helps reduce the chance of introducing bugs in Fortran codes because it guarantees that you are using the same kind-value throughout your program (the chance that you do need use different kind-values in different parts of a code is rare) and thus avoids the frequently encountered bugs of kind-value mismatch between dummy and actual arguments in a function call.

7 Comments

Recommended by whom? This is the archaic way, not the modern way. It is also not just about "precision".
Wait, what? Recommended by whom [2]? 1) Explicit is better than implicit, 2) Kind specifiers is the most portable alternative, 3) 8 byte float is about data storage not about precision.
Recommented by tokamak fusion scientists from General Atomics. They gave a list of FORTRAN coding conventions used in the GACODE build system. All latest General Atomics modeling codes follow these conventions. What's nice about them is that, when porting the code to any new platform (cori, titan, summit ...), all that's needed is to set up the correct platform environment variable in the makefile. The GACODE build system has been set up on many computer systems in the world.
@YoujunHu a real number stored in 8 bytes can be (and probably will, obviously) more acurate than a 4 bytes, but does this say anything about how much precise it is? how many decimal places? maximum exponent? If you care about a specific requirement in precision, use selected_real_kind. If you care about a specific storage size, use iso_fortran_env kind constants. Refer to this answer for more details.
I am not saying -fdefault-real-8 is evil, I am saying that this is not the most recommended approach by Fortran community, because it changes implictly the behaviour you expect when you look at the code. Help forums are full of: "why my calls to libraries (Lapack, mkl...) fail or give wrong result when the signature of the function seems to match the passed arguments?". Oh, it's because there is a line in the makefile (totally away from the source code) that says that, in this project, double precision actually means double double precision... ¬¬
|