Fortran: the largest and the smallest integer - fortran

Fortran is completely new for me, can anybody help me to solve the follwing problem? I want to find out all the integer kind numbers and the largest and the smallest value for each kind number on my pc. I have code listed below:
program intkind
implicit none
integer :: n=1
integer :: integer_range =1
do while(integer_range /= -1)
print*, "kind_number ", selected_int_kind(n)
call rang(integer_range)
n = n *2
integer_range = selected_int_kind(n)
end do
contains
subroutine rang(largest)
integer largest
print*, huge(largest)
end subroutine
end
The integer kind numbers what I get are : 1,2,4,8.
Why is each largest integer for each kind number the same: 2147483647? And is there a intrinsic function for the smallest integer?
How can I keep the integer kind number when the subroutine rang is called? I think it is the key to the largest integer.

Your subroutine:
subroutine rang(largest)
integer :: largest
print *, huge(largest)
end subroutine
takes as input a default-sized integer, and prints the largest possible value that will fit in that default-sized integer. It will always return huge(default integer) which is, on most systems, huge(4-byte-integer), or 2147483647. huge considers only the variable type; it doesn't interpret the variable in any way. The only way you could do what you're trying to do above is with parameterized derived types, which are new enough that support for it in compilers is still a little spotty.
If you want to take a look at ranges of different KINDs of INTEGERs, you'll have to use different variables:
program integerkinds
use iso_fortran_env
implicit none
integer :: i
integer(kind=int8) :: i8
integer(kind=int16) :: i16
integer(kind=int32) :: i32
integer(kind=int64) :: i64
integer(kind=selected_int_kind(6)) :: j6
integer(kind=selected_int_kind(15)):: j15
print *,'Default:'
print *, huge(i)
print *,'Int8:'
print *, huge(i8)
print *,'Int16:'
print *, huge(i16)
print *,'Int32:'
print *, huge(i32)
print *,'Int64:'
print *, huge(i64)
print *,''
print *,'Selected Integer Kind 6:'
print *, huge(j6)
print *,'Selected Integer Kind 15:'
print *, huge(j15)
end program integerkinds
Running gives:
$ ./intkinds
Default:
2147483647
Int8:
127
Int16:
32767
Int32:
2147483647
Int64:
9223372036854775807
Selected Integer Kind 6:
2147483647
Selected Integer Kind 15:
9223372036854775807

Purely as an addendum, or alternate perspective, Fortran variables are defined in terms of the number of bytes of memory allocated to the var. Indeed, all comparable compilers define vars in terms of bytes allocated, otherwise it would be very difficult for the system to allocate/store in memory, and very very difficult to perform arithmetic etc without such.
For some, like me, it is easier to see what is going on by using a slightly older notation (rather than the "kind konfusion". In particular, very many compilers provide a direct 1:1 correspondence between Kind and bytes/var, which then makes calculation of largest/smallest Integer fairly straightforward (some compiler use a non-linear or non-direct correspondence). Though be sure to take note of the portability assistance at the end. For example
Integer(1) :: Int1 ! corresponds to a 1 byte integer
Integer(2) :: Int1 ! corresponds to a 2 byte integer
Integer(4) :: Int1 ! corresponds to a 4 byte integer
Integer(8) :: Int1 ! corresponds to an 8 byte integer
Similar notation applies to other Fortran types (Real, Logical, etc). All var types have a default number of bytes allocated if the "size" is not specified.
The maximum number of bytes for a particular type also depends on compiler and system (e.g. Integer(16) is not available on all systems, etc).
A byte is 8 bits, so a single byte should be able to accommodate the largest value of 2^8 = 256 if numbering from 1, or = 255, when starting from 0.
However, in Fortran, (almost all) numeric vars are "signed". That means somewhere in the bit representation one bit is required to track whether the number is a +ve number or a -ve number. So in this example, the max would be 2^7, since one bit is "lost/reserved" for the "sign" information. Thus, the values possible for a signed 1-byte integer are -127:+128 (notice the Abs(limits) sum to 255, since "0" takes up one place, for a total of 256 "things", as it should be).
A similar rule applies for all such vars, with simply the exponent "n", in 2^n, varying based on the number of bytes. For example, an Integer(8) var has 8 bytes, or 64 bits, with 1 bit lost/reserved for sign information, so the largest possible value would be 2^63 = 9223372036854775808, if numbering from 1, or = 4611686018427387904 when starting from 0.
The standard Integer data model would be generalised as:
IntNum = s * Sum[ w(k) * 2 ^ (k-1), k=1:(NumBytes*8)-1],
where s = "sign" (+/-1), w(k) is either 1 or 0 for the kth bit value.
One need not use explicit numbers or env vars in the type declarations; user defined compile time constants (i.e. Parameters) are permitted. For example
Integer, Parameter :: DP = Kind(1.0d0) ! a standard Double Precision/8-byte declaration
Integer, Parameter :: I4B = 4 ! NOTICE, here the "Integer" bit has not been explicitly "sized", so defaults to "Integer(4)"
!
Real(DP) :: ADoublePrecReal ! an 8-byte Real (approx 15 decimal places with exp +/- approx 300, see Real data model)
!
Integer(I4B) :: AStandardInt ! a 4-byte integer.
Since the Parameter statement can be in another Module accessible via Use etc, it is a simple matter to recompile large complex code for alternate definitions of "precision" desired. For example, if DP is edited to Kind(1.0), then everywhere that declaration is applied will become "single precision" Real.
The Fortran intrinsic functions Huge(), Tiny() etc help to determine what is possible on a given system.
Much more can be accomplished with Fortran "bit" intrinsics, and other tools/methods.

Related

How to resolve the issue with signed zero?

I came to know about 'signed zeroes' only now as I am trying to deal with complex numbers. Here is the problem:
PROGRAM sZ
IMPLICIT NONE
REAL(KIND(0.d0)),PARAMETER :: r=0.2
COMPLEX(KIND(0.d0)) :: c0
c0=(0.0,0.5); print*,sqrt(c0**2-r)
c0=(-0.0,0.5); print*,sqrt(c0**2-r)
END PROGRAM sZ
The sign of the imaginary part changes.
(0.0000000000000000,0.67082039547127081)
(0.0000000000000000,-0.67082039547127081)
Any instructions/suggestions to resolve this issue are very much welcome.
The values you see follow from the intermediate step and the specification of the sqrt intrinsic.
The final result depends on the value of the argument to sqrt: as the result has real part the sign of the result's imaginary part is that of the sign of the argument's imaginary part.
What are the signs of the imaginary parts of the two arguments? The imaginary parts of (0.,0.5) and (-0.,0.5) squared are positive in the first case and negative in the second (with the expected implementation of signed zero). Subtracting a real entity does not affect the sign of the imaginary part of the object which becomes the argument to sqrt.
At one level, you are getting the correct result so the only thing to resolve is your expectation of getting the same result. However, consider
implicit none
complex :: z1=(-1.,0.), z2=(-1.,-0.)
print*, z1==z2, SQRT(z1)==SQRT(z2)
end program
It is easy to see why this is confusing even if correct. If we don't want this to happen, we can force any zero imaginary part to be of one particular sign (say, non-negative):
! Force imaginary part away from -0.
if (z%Im==0.) z%Im = 0.
(A comment for this is very necessary.)
We can access and set the imaginary part of a complex variable using the z%Im designator, but this is not possible for general expressions. You may want to create a function for more general use:
implicit none
complex :: z1=(-1.,0.), z2=(-1.,-0.)
print*, z1==z2, SQRT(z1)==SQRT(z2)
print*, z1==z2, SQRT(design_0imag(z1))==SQRT(design_0imag(z2))
contains
pure complex function design_0imag(z) result(zp)
complex, intent(in) :: z
zp = z
if (zp%Im==0.) zp%Im = 0.
end function design_0imag
end program
As shown by other answers, there are several ways to implement logic replacing -0 with 0 (leaving other values unchanged). Remember that you experience this only when the result is purely imaginary.
you could do something like this, so a signed (negative) zero is just caught and replaced with zero.
PROGRAM sZ
IMPLICIT NONE
REAL(KIND(0.d0)),PARAMETER :: r=0.2
COMPLEX(KIND(0.d0)) :: c0
REAL(KIND(0.d0)),PARAMETER :: i = -0.0
REAL(KIND(0.d0)),PARAMETER :: j = 0.5
REAL(KIND(0.d0)),PARAMETER :: zero = 0.0
if (i .EQ. 0) then
c0 = (zero, j); print*,sqrt(c0**2-r)
else
c0=(i, j); print*,sqrt(c0**2-r)
end if
END PROGRAM sZ
I have devised one little hack to remove this signed zeros.
PROGRAM sZ
IMPLICIT NONE
REAL(KIND(0.d0)),PARAMETER :: r=0.2
COMPLEX(KIND(0.d0)) :: c0,zero
zero=(0.0,0.0)
c0=(0.0,0.5); c0=c0+zero; print*,sqrt(c0**2-r)
c0=(-0.0,0.5); c0=c0+zero; print*,sqrt(c0**2-r)
END PROGRAM sZ
Now the results are same. :)
However, I would like to know more on this. When are signed zeroes necessary?

Apparent mixed-mode arithmetic from a Fortran intrinsic function

What I'm doing is very straightforward. Here are the relevant declarations:
USE, INTRINSIC :: ISO_Fortran_env, dp=>REAL64 !modern DOUBLE PRECISION
REAL(dp), PARAMETER :: G_H2_alpha = 1.57D+04, G_H2_beta = 5.3D+03, G_H2_gamma = 4.5D+03
REAL(dp) :: E_total_alpha, E_total_beta, E_total_gamma, P_H2_sed
Usage:
P_H2_sed = G_H2_alpha * E_total_alpha + G_H2_beta * E_total_beta * G_H2_gamma * E_total_gamma
where E_total_alpha, E_total_beta, and E_total_gamma are just running dp totals inside various loops. I ask for the nearest integer NINT(P_H2_sed) and get -2147483648, which looks like mixed-mode arithmetic. The float P_H2_sed returns 2529548272025.4888, so I would expect NINT to return 2529548272026. I didn't think it was possible to get this kind of result from an intrinsic function. I haven't seen this since my days with the old F77 compiler. I'm doing something bad, but what is the question.
NINT, by default, returns an integer with default type parameter, that usually is equivalent to int32.
An integer of this kind cannot represent a number as high as 2529548272026. The maximum representable number is 2^31-1, that is 2147483647. The result you are getting is similar to that, but is the lowest representable number, -2147483648 (equivalent o all 32 bits set to 1).
To get a result of other kind from NINT, pass an optional parameter named kind, like this: NINT(P_H2_sed, kind=int64).

Function type does not match the function definition

I am new to Fortran, writing some practice code with a function that returns Farenheit from Celsius
program Console1
implicit none
real, parameter :: ikind = selected_real_kind(p=15)
real (kind = ikind):: c,f,o,faren
print *, "enter a temperature in degrees celsius"
read *, c
write(*,10) "farenheit =", faren(c)
10 format(a,f10.8)
end program Console1
function faren(c)
real, parameter :: ikind = selected_real_kind(p=15)
real (kind = ikind):: c,f
faren = (9/5)*c + 32
end function faren
I get an error #7977 : The type of the function reference does not match the type of the function definition.
So with that if i change function faren(c) to real function faren(c)
I get the same error, but the types are the same?
Am i missing something? Do I have to define the function in the main program?
There are several issues in addition to the structural/code arrangement ones already noted.
First, KIND is an integer, so you want to change
real, parameter :: ikind = selected_real_kind(p=15)
to
integer, parameter :: ikind = selected_real_kind(p=15)
Ideally, you want to define that in only one place (i.e. in a module) and reference it from both your main program and the function, but the code should be fine as it is for test purposes.
A second issue that often trips up newcomers to Fortran (and Python2) is that real numbers and integers are distinct types and are not generally interchangeable.
faren = (9/5)*c + 32
simplifies to
faren = (1)*c + 32
because integer division has an integer result; 9/5 = 1
Fortran is picky about numerical values (that's sort of the whole point of the language) so what you probably want is:
faren = (9.0 / 5.0) * c + 32.0
Or more precisely, if faren is defined with a specific precision of ikind,
faren = (real(9.0,ikind) / real_(5.0,ikind)) * c + real(32.0,ikind)
or
faren = (9.0_ikind / 5.0_ikind) * c + 32.0_ikind
This syntax tends to make people's heads explode. Welcome to modern fortran ;)
The last issue deals with the horrors of Fortran I/O. From a design standpoint, you need to know what results the user expects and make sure the output format can display them. The legitimate range of input values for c is -273.15 (give or take) to some upper bound which relies on the use case for the code. If you're dealing with cooking temperatures, you probably won't exceed 400.0; if you're doing fusion research, you could be going much higher. Are 8 figures past the decimal useful or believable? In this case, we're just testing the code so we may not need a lot of precision in the output; you'll want to change the output format to something like:
10 format(a,es10.2)
or
10 format(a,g16.8)
You need to ensure the total field width (the number before the dot) can contain the decimal part (the number after the dot) along with the integer part of the number, plus the space needed to show sign and exponent. For scientific notation, four characters are eaten by mantissa sign, decimal point, 'E' and exponent sign. It may be safer just starting out to use an output format of *; it's frustrating to fight with numerics and formatting simultaneously.
That is a good effort and simple start to work through the nuance, so a good question.
Personally I would use reals for the math, rather the 9/5, and use a module. In this example you could pass in a real or a double to C2Faren and the interface/procedure will sort out whether to use the real or the double version. Then you have a few options in case you want different precision.
You could also use the ISO_C_BINDING if you do mixed language...
MODULE MyTEMPS
PRIVATE
DOUBLE PRECISION, PARAMETER :: C2F_ScaleFact = 1.8D0
DOUBLE PRECISION, PARAMETER :: F2C_ScaleFact = /(1.0D0 / 1.8D0)/
DOUBLE PRECISION, PARAMETER :: F2C_Offset = 32.0D0
PUBLIC Faren2C
INTERFACE C2Faren
MODULE PROCEDURE C2Faren_Real, C2Faren_DBL
END INTERFACE
CONTAINS
!========= REAL VERISON =========
REAL FUNCTION C2Faren_Real(c)
IMPLICIT NONE
real, INTENT(IN ) :: c
C2Faren_Real = ( C*F2C_ScaleFact ) + F2C_Offset
RETURN
END FUNCTION C2Faren_Real
!========= DOUBLE VERSION =========
DOUBLE PRECISION FUNCTION C2Faren_DBL(c)
IMPLICIT NONE
DOUBLE PRECISION , INTENT(IN ) :: c
C2Faren_DBL = ( C*F2C_ScaleFact ) + F2C_Offset
RETURN
END FUNCTION C2Faren_DBL
!========= REAL VERSION (Faren to Centigrade) =========
REAL FUNCTION faren2C(Faren)
IMPLICIT NONE
REAL, INTENT(IN ) :: Faren
faren2C = (faren - F2C_Offset) / F2C_ScaleFact
RETURN
END FUNCTION faren2C
END MODULE MyTEMPS
Then your program uses the module via USE n the second line...
program Console1
USE MyTEMPS !<== Here
implicit none
real :: c, f
DOUBLE PRECISION :: Dc, Df ! No way to get Df to C or DC in the module (yet)!
print *, "enter a temperature in degrees celsius"
read *, c
write(*,10) "farenheit =", C2faren(c)
10 format(a,f10.6)
Dc = C
write(*,12) "farenheit =", C2faren(Dc)
12 format("DBL:",A,f10.6)
F = Dc
write(*,14) "Centigrade =", faren2C(F)
14 format("DBL:",A,f10.6)
end program Console1
So/and the main advantage of the module is when you end up wanting to use this stuff in a variety of programs and test and sort out the module once... Usually people put this sort of stuff (lots of modules) in a library, when the module(s) have lot of functions.
You could also put just the real, parameter :: ikind = selected_real_kind(p=15) into a module and use that in both the program and the function and you would be there. You were real close, and it mostly a matter of style and utility.
For Intel Fortran you can use REAL(KIND=4) and REAL(KIND=8)... Which I do, but that is not portable to gfortran, so it is probably a better habit to use the ISO_C_BINDING or just use REAL and DOUBLE PRECISION.
Modules are great but if you have a very simple code another way to work is to put the subroutines and functions in your main program. The trick is to put them after the word contains:
program xxx
stuff
contains
subroutine yyy
function zzz
end program xxx
In this way the functions can see into the contents of the main program so you don't have to re-declare your parameters and you are likely to get more meaningful error messages.
Since you are new I have a great resource I learned a lot from to share:
http://www.uv.es/dogarcar/man/IntrFortran90.pdf

fortran: compilation in 64-bit system producing 32-bit integer overflow error [duplicate]

Fortran is completely new for me, can anybody help me to solve the follwing problem? I want to find out all the integer kind numbers and the largest and the smallest value for each kind number on my pc. I have code listed below:
program intkind
implicit none
integer :: n=1
integer :: integer_range =1
do while(integer_range /= -1)
print*, "kind_number ", selected_int_kind(n)
call rang(integer_range)
n = n *2
integer_range = selected_int_kind(n)
end do
contains
subroutine rang(largest)
integer largest
print*, huge(largest)
end subroutine
end
The integer kind numbers what I get are : 1,2,4,8.
Why is each largest integer for each kind number the same: 2147483647? And is there a intrinsic function for the smallest integer?
How can I keep the integer kind number when the subroutine rang is called? I think it is the key to the largest integer.
Your subroutine:
subroutine rang(largest)
integer :: largest
print *, huge(largest)
end subroutine
takes as input a default-sized integer, and prints the largest possible value that will fit in that default-sized integer. It will always return huge(default integer) which is, on most systems, huge(4-byte-integer), or 2147483647. huge considers only the variable type; it doesn't interpret the variable in any way. The only way you could do what you're trying to do above is with parameterized derived types, which are new enough that support for it in compilers is still a little spotty.
If you want to take a look at ranges of different KINDs of INTEGERs, you'll have to use different variables:
program integerkinds
use iso_fortran_env
implicit none
integer :: i
integer(kind=int8) :: i8
integer(kind=int16) :: i16
integer(kind=int32) :: i32
integer(kind=int64) :: i64
integer(kind=selected_int_kind(6)) :: j6
integer(kind=selected_int_kind(15)):: j15
print *,'Default:'
print *, huge(i)
print *,'Int8:'
print *, huge(i8)
print *,'Int16:'
print *, huge(i16)
print *,'Int32:'
print *, huge(i32)
print *,'Int64:'
print *, huge(i64)
print *,''
print *,'Selected Integer Kind 6:'
print *, huge(j6)
print *,'Selected Integer Kind 15:'
print *, huge(j15)
end program integerkinds
Running gives:
$ ./intkinds
Default:
2147483647
Int8:
127
Int16:
32767
Int32:
2147483647
Int64:
9223372036854775807
Selected Integer Kind 6:
2147483647
Selected Integer Kind 15:
9223372036854775807
Purely as an addendum, or alternate perspective, Fortran variables are defined in terms of the number of bytes of memory allocated to the var. Indeed, all comparable compilers define vars in terms of bytes allocated, otherwise it would be very difficult for the system to allocate/store in memory, and very very difficult to perform arithmetic etc without such.
For some, like me, it is easier to see what is going on by using a slightly older notation (rather than the "kind konfusion". In particular, very many compilers provide a direct 1:1 correspondence between Kind and bytes/var, which then makes calculation of largest/smallest Integer fairly straightforward (some compiler use a non-linear or non-direct correspondence). Though be sure to take note of the portability assistance at the end. For example
Integer(1) :: Int1 ! corresponds to a 1 byte integer
Integer(2) :: Int1 ! corresponds to a 2 byte integer
Integer(4) :: Int1 ! corresponds to a 4 byte integer
Integer(8) :: Int1 ! corresponds to an 8 byte integer
Similar notation applies to other Fortran types (Real, Logical, etc). All var types have a default number of bytes allocated if the "size" is not specified.
The maximum number of bytes for a particular type also depends on compiler and system (e.g. Integer(16) is not available on all systems, etc).
A byte is 8 bits, so a single byte should be able to accommodate the largest value of 2^8 = 256 if numbering from 1, or = 255, when starting from 0.
However, in Fortran, (almost all) numeric vars are "signed". That means somewhere in the bit representation one bit is required to track whether the number is a +ve number or a -ve number. So in this example, the max would be 2^7, since one bit is "lost/reserved" for the "sign" information. Thus, the values possible for a signed 1-byte integer are -127:+128 (notice the Abs(limits) sum to 255, since "0" takes up one place, for a total of 256 "things", as it should be).
A similar rule applies for all such vars, with simply the exponent "n", in 2^n, varying based on the number of bytes. For example, an Integer(8) var has 8 bytes, or 64 bits, with 1 bit lost/reserved for sign information, so the largest possible value would be 2^63 = 9223372036854775808, if numbering from 1, or = 4611686018427387904 when starting from 0.
The standard Integer data model would be generalised as:
IntNum = s * Sum[ w(k) * 2 ^ (k-1), k=1:(NumBytes*8)-1],
where s = "sign" (+/-1), w(k) is either 1 or 0 for the kth bit value.
One need not use explicit numbers or env vars in the type declarations; user defined compile time constants (i.e. Parameters) are permitted. For example
Integer, Parameter :: DP = Kind(1.0d0) ! a standard Double Precision/8-byte declaration
Integer, Parameter :: I4B = 4 ! NOTICE, here the "Integer" bit has not been explicitly "sized", so defaults to "Integer(4)"
!
Real(DP) :: ADoublePrecReal ! an 8-byte Real (approx 15 decimal places with exp +/- approx 300, see Real data model)
!
Integer(I4B) :: AStandardInt ! a 4-byte integer.
Since the Parameter statement can be in another Module accessible via Use etc, it is a simple matter to recompile large complex code for alternate definitions of "precision" desired. For example, if DP is edited to Kind(1.0), then everywhere that declaration is applied will become "single precision" Real.
The Fortran intrinsic functions Huge(), Tiny() etc help to determine what is possible on a given system.
Much more can be accomplished with Fortran "bit" intrinsics, and other tools/methods.

Determine Fortran derived type size in memory

The Fortran intrinsic function transfer can be used to covert a derived type into a real or integer array. This is potentially very useful when working in legacy systems which relies on arrays of primitive types (integer, real etc.) for persistence.
The code below runs at least on ifort and gfortran and converts a simple derived type example to an integer array (updated with solution):
program main
implicit none
integer, parameter :: int_mem_size = storage_size(1)
type subtype
integer a
double precision b
end type subtype
type :: mytype
integer :: foo
double precision :: bar
type(subtype) :: some_type
end type
type(mytype) :: my_var
type(subtype) :: my_subtype
! Old version: integer :: x(30)
integer, allocatable :: x(:)
integer :: mem_size
!Allocate array with required size
mem_size = storage_size(my_var)
allocate(x(mem_size/int_mem_size))
my_subtype%a = 1
my_subtype%b = 2.7
my_var%foo = 42
my_var%bar = 3.14
my_var%some_type = my_subtype
write(*,*) "transfering..."
x = transfer(my_var, x)
write(*,*) "Integer transformation:", x
end program main
On my PC, this is the output (this result is at least platform dependent):
transfering...
Integer transformation: 42 0 1610612736 1074339512
999 0 -1610612736 1074108825
My problem is that I have "guessed" that a 30 element long integer array is large enough to store this data structure. Is there a way I can determine how large the array needs to be to store the whole data structure?
If you have a Fortran 2008 compliant compiler, or one that is compliant enough, you will find the intrinsic function storage_size which returns the number of bits used to store its argument. Failing that most compilers that I am familiar with implement a non-standard function to do this; the Intel Fortran compiler has a function called sizeof which returns the number of bytes required to store its argument.