I'm trying to add two integers(kind=4) that can be large enough to produce an integer(kind=8). I'm not sure if this is possible, but I made a few tests trying to make it work:
!gfortran, gcc version 5.4.0 20160609
program hello
use iso_fortran_env
integer, parameter :: i64 = int64
integer(kind=4) :: a1, a2
integer(kind=8) :: b1, b2
integer(kind=8) :: c
integer(kind=8) :: ugly
a1 = 2023123123 !kind(4)
a2 = a1 !kind(4)
b1 = 2023123123 !kind(8)
b2 = b1 !kind(8)
! sum integers of kind=8 that surely will lead to a kind=8
c = b1+b2
print*,c
! sum integers of kind=4 and kind=8 that will lead to a kind=8
c = a1+b1
print*,c
! sum integers of kind=4 which may lead to a kind=8
c = a1+a2
print*,c
! try to tell gfortran to make a kind(4) behave as a kind(8)
! for that operation
c = a1+a2_i64
print*,c
! ugly workaround fail - 64 bit 0 on last position
ugly = 0
c = a2+a1+ugly
print*,c
! ugly workaround ok - 64 bit 0 on first position
ugly = 0
c = ugly+a2+a1
print*,c
! ugly workaround ok - divide in two operations
c = a1+ugly
c = c+a2
print*,c
end program hello
The output of the script is
4046246246 ! kind(8) + kind(8) = kind(8) -> ok
4046246246 ! kind(4) + kind(8) = kind(8) -> ok, but not sure if it always work
-248721050 ! kind(4) + kind(4) = kind(8) -> NOT OK
2023123072 ! kind(4) + kind(4)_i64 = kind(8) -> NOT OK
-248721050 ! ugly workaround summing 0(kind=8) -> FAIL
4046246246 ! ugly workaround summing 0(kind=8) -> OK
4046246246 ! another ugly work around -> OK
Does anyone know how if its possible to add two integer(kind=4) resulting in a integer(kind=8) WITHOUT that very ugly workaround?
If a
and b
are integers then the expression a+b
is an integer. If a
and b
of the same kind, then the expression is of that kind. If they are of different kind but one has greater decimal exponent range then the expression is of that kind.
If a
and b
are of the same kind as a+b
then there is no conversion. An operand (a
or b
) which is of different kind from a+b
is treated as though it is converted to that kind.
So, if you want the result to be of kind 8
(assuming that is the one of greater range) then you need one (or both) of the operands to be of kind 8
. In the case of the question:
b1+b2
both are kind 8
;a1+b1
, b1
of kind 8
, a1
converted to that kind;a1+a2
, both are kind 4
, not converted, result of kind 4
.In the case of a+b+c
then the expression is treated as (a+b)+c
:
a2+a1+ugly
, a2+a1
has no conversion in its evaluation, but is converted for sum (a2+a1)+ugly
ugly+a2+a1
, ugly+a2
has a2
converted to kind 8
, then a1
converted to kind 8
to give result of kind 8
.So, if a2+a1
is not valid for range then a2+a1+ugly
has that same problem, but ugly+a2+a1
has both a1
and a2
treated as kind 8
.
Finally:
int(a1,8)+int(a2,8)
has explicit conversion to kind 8
;int(a1,8)+a2
, a1+int(a2,8)
has the expected behaviour. All of these are ugly: don't use kinds like 4
and 8
, especially if you have int64
available and behaving as you want.