gfortran variable declaration to store 32-bit integer netcdf [duplicate] - fortran

I'm trying to learn Fortran and I'm seeing a lot of different definitions being passed around and I'm wondering if they're trying to accomplish the same thing. What is the difference between the following?
integer*4
integer(4)
integer(kind=4)

In Fortran >=90, the best approach is use intrinsic functions to specify the precision you need -- this guarantees both portability and that you get the precision that you need. For example, to obtain integers i and my_int that will support at least 8 decimal digits, you could use:
integer, parameter :: RegInt_K = selected_int_kind (8)
integer (kind=RegInt_K) :: i, my_int
Having defined RegInt_K (or whatever name you select) as a parameter, you can use it throughout your code as a symbol. This also makes it easy to change the precision.
Requesting 8 or 9 decimal digits will typically obtain a 4-byte integer.
integer*4 is an common extension going back to old FORTRAN to specify a 4-byte integer. Although, this syntax isn't and was never standard Fortran.
integer (4) or integer (RegInt_K) are short for integer (kind=4) or integer (kind=RegInt_K). integer (4) is not the same as integer*4 and is non-portable -- the language standard does not specify the numeric values of kinds. Most compilers use the kind=4 for 4-byte integers -- for these compilers integer*4 and integer(4) will provide the same integer type -- but there are exceptions, so integer(4) is non-portable and best avoided.
The approach for reals is similar.
UPDATE: if you don't want to specify numeric types by the required precision, but instead by the storage that they will use, Fortran 2008 provides a method. reals and integers can be specified by the number of bits of storage after useing the ISO_FORTRAN_ENV module, for example, for a 4-byte (32-bit) integer:
use ISO_FORTRAN_ENV
integer (int32) :: MyInt
The gfortran manual has documentation under "intrinsic modules".

Just one more explicit explanation what the kind is. The compiler has a table of different numerical types. All integer types are different kinds of the basic type -- integer. Let's say the compiler has 1 byte, 2 byte, 4 byte, 8 byte and 16 byte integer (or real) kinds. In the table the compiler has an index to each of this kind -- this index is the kind number.
Many compilers choose this numbering:
kind number number of bytes
1 1
2 2
4 4
8 8
16 16
But they can choose any other numbering. One of the obvious possibilities is
kind number number of bytes
1 1
2 2
3 4
4 8
5 16
There are indeed compilers (at least g77 and NAG) which choose this approach. There are also options to change this. Therefore kind numbers are not portable integer(kind=4) or integer(4) means a 4 byte integer or a 8-bytes integer depending on the compiler.
integer*4 is portable in the sense it always means 4 bytes. But on the other hand it is not portable because it has never been part of any standard. Programs using this notation are not valid Fortran 77, 90 or any other Fortran.
To see the right options how to set the kind numbers see M.S.B.'s answer.
The same concept holds for real data types. See Fortran 90 kind parameter (the mataap's answer).

I will make reference to this enlightening article, wrote recently by #SteveLionel, and try cover some details that are not present in the other answers so far:
The syntax shown in integer*n or real*n was a common extension provided by compilers long time ago, when different computer architectures started to have different designs for in-memory format of integer and real values, where n was the size in bytes of the value stored. However, that said nothing about range or precision of those values: different implementations of a 16bit integer, for example, could provide different ranges and limit values.
Register sizes could be 8, 12, 16, 30, 32, 36, 48, 60 or 64 bits, some CDC machines had ones-complement integers (allowing minus zero for an integer!), the PDP-11 line had several different floating point formats depending on the series, the IBM 360/370 had "hex normalization" for its floating point, etc [...] So popular were these extensions that many programmers thought (and even today many think) that this syntax is standard Fortran; it isn't!
When Fortran 90 came out, kind parameters were added to the language, along with intrinsic inquiry functions (specially kind, selected_int_kind and selected_real_kind, but also others, like precision, digits, epsilon...) to aid the programmer to specify minimun requirements for precision and range of numeric types (still, no official mention to storage model or bytes). The syntax is integer(kind=n) or even integer(n), where n is a constant value corresponding to a kind of integer supported by the compiler. For literal constants, the syntax is 12_n or 3.4e-2_n.
The advantage of this solution was that Fortran didn't (and still don't) make any assumptions about the implementation details of data-types other than the results of the inquiry functions used to choose the type, so the code is parameterized by the problem being solved, not by the language or the hardware. The gotcha is, as said in other answers, each compiler can choose their kind numbers, thus assuming magic number like integer(4) is not portable.
Also with Fortran 90 came the concept of default kinds, that is what you get when you don't specify a kind.
The default kinds were implementation dependent, though up through Fortran 2008 a compiler was required to support only one integer kind and two real kinds. (That's still true in Fortran 2018, but there's an added requirement that at least one integer kind support 18 decimal digits.) If you write a constant literal without a kind specifier, you got the default kind.
With Fortran 2003 and the inclusion of the intrinsic module ieee_arithmetic, you can inquire and select a real type with IEEE floating point capabilities, if avaliable.
There are architectures where both IEEE and non-IEEE floating types are available, such as the HP (formerly Compaq formerly DEC) Alpha. In this case you can use IEEE_SELECTED_REAL_KIND from intrinsic module IEEE_ARITHMETIC to get an IEEE floating kind. And what if there is no supported kind that meets the requirements? In that case the intrinsics return a negative number which will (usually, depending on context) trigger a compile-time error.
Finally, Fortran 2003 brought the iso_fortran_env intrinsic module, that had functions to inquire the storage size of the types implemented by a compiler, with intrinsics like numeric_storage_size and bit_size. Another addition of Fortran 2003 revision was the iso_c_binding intrinsic module, that provided kind parameter values to guarantee compatibility with C types, in storage, precision and range.
Intrinsic module ISO_C_BINDING declares constants for Fortran types that are interoperable with C types, for example C_FLOAT and C_INT. Use these if you're declaring variables and interfaces interoperable with C.
As a final note, I will mention the recent Fortran 2008 Standard, that extended intrinsic module iso_fortran_env to include named constants int8, int16, int32m int64, real32, real64 and real128, whose values correspond to the kinds of integer and real kinds that occupy the stated number of bits. The gotcha is that those constants only assure storage size, not precision or range. Only use them when this is exactly what you want.
In my view, this is little better than the old *n extension in that it tells you that a type fits in that many bits, but nothing else about it. As an example, there's one compiler where REAL128 is stored in 128 bits but is really the 80-bit "extended precision" real used in the old x86 floating point stack registers. If you use these you might think you're using a portable feature, but really you're not and may get bitten when the kind you get doesn't have the capabilities you need.

Related

Very small numbers in Fortran

Is it possible to achieve very small numbers in Fortran like 1E-1200? I know how to do it in python, but my code for master's thesis runs too slow. My supervisor recommends me to use Fortran, but I am not sure if this is a problem.
The previous answers suggesting use of REAL128 from ISO_FORTRAN_ENV describe a non-portable solution. What you would get here is a real type whose representation is 128 bits, but that says nothing about the range or precision of the type! For example, some IBM systems have a 128-bit real kind that is actually two doubles with an offset exponent. This gets you more precision but not significantly more range.
The proper way to do this is to use the SELECTED_REAL_KIND intrinsic function to determine the implementation's kind that supports the desired range. For example:
integer, parameter :: bigreal = SELECTED_REAL_KIND(R=1200)
real(KIND=bigreal) :: x
If the implementation doesn't have a real kind that can represent a value with a decimal exponent of plus or minus 1200, you'll get an error, otherwise you'll get the smallest appropriate kind.
You could also specify a P= value in the call to indicate what minimum precision (in decimal digits) you need.
The short answer is yes.
Modern compilers typically support so-called quad precision, a 128-bit real. A portable way to access this type is using the ISO_FORTRAN_ENV. Here is a sample program to show how big and small these numbers get:
program main
use ISO_FORTRAN_ENV, only : REAL32, REAL64, REAL128
! -- tiny and huge grab the smallest and largest
! -- representable number of each type
write(*,*) 'Range for REAL32: ', tiny(1._REAL32), huge(1._REAL32)
write(*,*) 'Range for REAL62: ', tiny(1._REAL64), huge(1._REAL64)
write(*,*) 'Range for REAL128: ', tiny(1._REAL128), huge(1._REAL128)
end program main
The types REAL32, REAL64, and REAL128 are typically known as single, double, and quad precision. Longer types have a larger range of representable numbers and greater precision.
On my machine with gfortran 4.8, I get:
mach5% gfortran types.f90 && ./a.out
Range for REAL32: 1.17549435E-38 3.40282347E+38
Range for REAL62: 2.2250738585072014E-308 1.7976931348623157E+308
Range for REAL128: 3.36210314311209350626E-4932 1.18973149535723176502E+4932
As you can see, quad precision can represent numbers as small as 3.4E-4932.
Most Fortran compilers support REAL128 data format which matches IEEE binary128. Some support also REAL80 with similar range, matching C long double. These don't have performance of REAL64 but should be much faster than python.

Defining constants of sufficient precision in Fortran [duplicate]

I have the following Fortran code:
Program Strange
Real(Kind=8)::Pi1=3.1415926535897932384626433832795028841971693993751058209;
Real(Kind=8)::Pi2=3.1415926535897932384626433832795028841971693993751058209_8;
Print*, "Pi1=", Pi1;
Print*, "Pi2=", Pi2;
End Program Strange
I compile with gfortran, and the output is:
Pi1= 3.1415927410125732
Pi2= 3.1415926535897931
Of course the second is correct, but should this be the case? It seems like Pi1 is being input to memory as a single precision number, and then put into a double precision memory slot. But this seems like an error to me. Am I correct?
I do know a bit of Fortran ! #Dougal's answer is correct though the snippet he quotes from is not, embedding the letter d into a real literal constant is not required (since Fortran 90), indeed many Fortran programmers now regard that approach as archaic. The snippet is also misleading in advising the use of 3.1415926535d+0 to initialise a 64-bit floating-point value for pi, it doesn't set enough of the digits to their correct values.
The statement:
Real(Kind=8)::Pi1=3.1415926535897932384626433832795028841971693993751058209
defines Pi1 to be a real variable of kind 8. The literal real value 3.1415926535897932384626433832795028841971693993751058209 is, however, a real value of default kind, most likely to be a 4-byte real on most current compilers. That seems to explain your output but do check your documentation.
On the other hand, the literal real value Pi2=3.1415926535897932384626433832795028841971693993751058209_8 is, by the suffixing of the kind specification, declared to be of kind=8 which is the same as the kind of the variable it is assigned to.
Three more points:
1) Don't fall into the trap of thinking that kind=8 means the same thing as 64-bit floating-point number or double. For many compilers it does, for some it doesn't. Kind numbers are not portable between Fortran implementations. They are, according to the standard, arbitrary positive integers. Better, with a modern compiler, would be to use the predefined constants from the intrinsic module iso_fortran_env, e.g.
use, intrinsic :: iso_fortran_env
...
real(real64) :: pi = 3.14159265358979323846264338_real64
There are other portable approaches to setting variable kinds using functions such as selected_real_kind.
2) Since the value of pi is unlikely to change during the execution of your program you might care to make it a parameter thus:
real(real64), parameter :: pi = 3.14159265358979323846264338_real64
3) It isn't necessary (or usual) to end Fortran statements with a ';' unless you want to have more than one statement on the same line in the source file.
I don't really know Fortran, but this page says:
The letter "d" must be embedded in the literal, otherwise, the compiler's pre-processor would round it off to be a Single Precision literal. For example, 3.1415926535 would be read as 3.141593 while 3.1415926535d+0 would be stored with all the digits intact. The letter "d" for double precision numbers has the same meaning as "e" for single precision numbers.
So it seems like your guess is correct.

Difference between code specified double precision and compiler option double precision

When writing a Fortran code, declaring a real variable by assigning kind=8 or double precision is one way of ensuring double precision. Another way is by not declaring anything explicitly in the code but rather using compiler options i.e -r8 (ifort) etc.
Is there a difference between the two?
Carefuly read this, though it is not 100 percent duplicate:
Fortran: integer*4 vs integer(4) vs integer(kind=4) and
Fortran 90 kind parameter.
kind=8 is non-portable and will not work in some compilers and teaching it to beginners, which can be seen even in one Coursera course should be criminally prosecuted.
There are different compiler options with different effect. Ones promote all 4 byte reals or integers to 8 byte ones. Other set default kind to be 8. This breaks some standard assumptions about storage and about double precision being able to hold more than the default kind. For example in gfortran:
-fdefault-real-8
sets the default real as 8 byte real. This is not completely the same as:
-freal-4-real-8
which promotes all 4 byte reals to 8 byte. You must be careful to understand the differences and generally using these options is not a very good practice.
The recommended solution is always the same, using a named constant:
integer, parameter :: rp = ...
and always using
real(rp) :: x
You can have more of these constants. Set the values of the constants according to the referenced question (real64, kind(1.d0), selected_real_kind(...)).

fortran default precision of numbers

I chose the precision in my code as :
integer, parameter ::psn=selected_real_kind(15,307)
then I write numbers appearing in the code with _psn, for example :
y=x/6._psn
I have many long expressions in code where many numbers appear in multiplications and divisions.
Now my question is: Is there any way to set precision of all numbers appearing in the code to be in a selected precision without explicitly specifying _psn everywhere?
You can set the default kind of real for the compiler...
ifort:
-r8 Makes default real and complex variables 8 bytes long.
gfortran:
-fdefault-real-8 Set the default real type to an 8 byte wide type.
Then, you can just use 1.e0 in your code...
In a portable manner, no.
If you choose convenience and readability over portability and maintainability, you can use compiler flags to change the default kind of REAL, like the accepted answer says.
It is important to understand that, in doing this, some assumptions that could be made based on the standard are often broken. Here are some examples:
The decimal precision of the double precision real approximation method shall be greater than that of the default real method. If you only promote REAL, that is probably lost, however at least in gfortran the commonly used flag for that end still upholds that rule:
-fdefault-real-8
Set the default real type to an 8 byte wide type. This option also affects the kind of non-double real constants like 1.0. This option promotes the default width of DOUBLE PRECISION and double real constants like 1.d0 to 16 bytes if possible.
A nonpointer scalar object that is default integer, default real, or default logical occupies a single numeric storage unit.
A nonpointer scalar object that is double precision real or default complex occupies two contiguous numeric storage units.
These last two imply there is something called a numeric storage unit, which is a basic building block of storage for numeric types, and default REAL, INTEGER and LOGICAL variables occupy 1 of it, while default DOUBLE PRECISION and COMPLEX occupy 2 of it. Needless to say, those contracts are also probably broken when you change default kinds.
It is possible (and even probable) that the affected code does not rely on any of those anyway, and in that case it would be harmless to use such flags. However, it remains important to understand the risks.

What does "real*8" mean?

The manual of a program written in Fortran 90 says, "All real variables and parameters are specified in 64-bit precision (i.e. real*8)."
According to Wikipedia, single precision corresponds to 32-bit precision, whereas double precision corresponds to 64-bit precision, so apparently the program uses double precision.
But what does real*8 mean?
I thought that the 8 meant that 8 digits follow the decimal point. However, Wikipedia seems to say that single precision typically provides 6-9 digits whereas double precision typically provides 15-17 digits. Does this mean that the statement "64-bit precision" is inconsistent with real*8?
The 8 refers to the number of bytes that the data type uses.
So a 32-bit integer is integer*4 along the same lines.
A quick search found this guide to Fortran data types, which includes:
The "real*4" statement specifies the variable names to be single precision 4-byte real numbers which has 7 digits of accuracy and a magnitude range of 10 from -38 to +38. The "real" statement is the same as "real*4" statement in nearly all 32-bit computers.
and
The "real*8" statement specifies the variable names to be double precision 8-byte real numbers which has 15 digits of accuracy and a magnitude range of 10 from -308 to +308. The "double precision" statement is the same as "real*8" statement in nearly all 32-bit computers.
There are now at least 4 ways to specify precision in Fortran.
As already answered, real*8 specifies the number of bytes. It is somewhat obsolete but should be safe.
The new way is with "kinds". One should use the intrinsic functions to obtain the kind that has the precision that you need. Specifying the kind by specific numeric value is risky because different compilers use different values.
Yet another way is to use the named types of the ISO_C_Binding. This question discusses the kind system for integers -- it is very similar for reals.
The star notation (as TYPE*n is called) is a non-standard Fortran construct if used with TYPE other than CHARACTER.
If applied to character type, it creates an array of n characters (or a string of n characters).
If applied to another type, it specifies the storage size in bytes. This should be avoided at any cost in Fortran 90+, where the concept of type KIND is introduced. Specifying storage size creates non-portable applications.