I have a subroutine ran_init ( length )
, in which one IF
statement works incorrectly.
The code below is a highly simplified version of my original code:
MODULE ran_state
USE nrtype
IMPLICIT NONE
INTEGER, PARAMETER :: K4B = SELECTED_INT_KIND ( 9 )
INTEGER ( K4B ), PARAMETER :: hg = HUGE ( 1_K4B ), hgm = -hg, hgng = hgm - 1
INTEGER ( K4B ), SAVE :: lenran = 0
CONTAINS
SUBROUTINE ran_init ( length )
USE nrtype; USE nrutil, ONLY: nrerror
IMPLICIT NONE
INTEGER ( K4B ), INTENT ( IN ) :: length
INTEGER ( K4B ) :: hgt
IF ( length < lenran ) RETURN
hgt = hg
PRINT *, hgt, hgt + 1, hgng, hgt + 1 - hgng
IF ( hgt + 1 .NE. hgng ) CALL nrerror ( 'ran_init: arith assump 3 fails' )
END SUBROUTINE
END MODULE ran_state
This code returns the result:
2147483647 -2147483648 -2147483648 0
nrerror: ran_init: arith assump 3 fails
STOP program terminated by nrerror
It is seen that values hgt + 1
and hgng
are equal to one another, but at the IF
statement these values are interpreted as unequal.
Why this can happen?
UPD №1 Some technical details:
- I use
gfortran
as a compiler - the command
gfortran --version
returns
GNU Fortran (Ubuntu 5.4.0-6ubuntu1~16.04.12) 5.4.0 20160609
- I compile my programs with flags
-O2 -Wall -Wextra -fbacktrace -fcheck=all -g -o
with a level of optimization does not affect on results.
- my OS is Ubuntu 16.04LTS 64-bit
UPD №2
I don't know WHY, but if one create a new variable, say, hgtp
of type INTEGER ( K4B )
and replace lines
hgt = hg
PRINT *, hgt, hgt + 1, hgng, hgt + 1 - hgng
IF ( hgt + 1 .NE. hgng ) CALL nrerror ( 'ran_init: arith assump 3 fails' )
with lines
hgt = hg
hgtp = hgt + 1
PRINT *, hgt, hgt + 1, hgng, hgt + 1 - hgng
IF ( hgtp .NE. hgng ) CALL nrerror ( 'ran_init: arith assump 3 fails' )
the IF-statement begins to interpret the condition hgtp .NE. hgng
as true.