I mean if I have integer 4 and integer 8 types, I need to be careful enough and make sure when the product of integer 4 becomes big enough and requires integer 8. It is OK to use minimal data type in this way, but occasionally it may not be the most convenient perhaps.
So I wonder, how do you guys deal with such situation?
Do you just use integer 8 everywhere or something?
I found using integer 8 everywhere is perhaps not the most convenient either, and may very slightly slow down the code. So I am not exactly sure what is the best approach.
In the original version of OP there was an array AAA(np,nd). I guess that internally, the processor should deal properly even with AAA(100000,100000) although the indices would overflow when simply multiplied.
In explicit calculations, however, one has to make sure there is no overflow and use proper kind(s). Note also, that with your declarations:
jjj will not be properly assigned if np*nd overflows in i4 kind. Consider sample program:
use iso_fortran_env, only: i4=>int32, i8=>int64
integer(i4) :: i=100000, j=100000
integer(i8) :: bi,bj
bi = i*j ! overflows, assigns bad value
bj = int(i,kind=i8)*j ! converted to i8 before multiplication
print *, bi, bj
end program main
! outputs: 1410065408 10000000000
On WSL2 compiling the code above with gfortran -g -ftracer -ftrapv int_overflow.f90 and running I get
(base) /mnt/c/fortran/test$ ./a.out
Program received signal SIGABRT: Process abort signal.
Backtrace for this error:
#0 0x7f99f6416700 in ???
#1 0x7f99f64158a5 in ???
#2 0x7f99f622e20f in ???
#3 0x7f99f622e18b in ???
#4 0x7f99f620d858 in ???
#5 0x7f99f63dea41 in ???
#6 0x55db6d14a1b8 in MAIN__
#7 0x55db6d14a297 in main
I use plain integer in my codes but should probably compile with -ftrapv to ensure that I am not missing integer overflow.
Sure if you add -ftrapv, signed overflow will cause exception. But w/o it, gfortran (ifort as well) produces code that silently ignores overflow giving bogus results. For ifort there seems to be no equivalent of -ftrapv. For other compilers I do not know.
I do not think any significant slowdown can be possible on 64-bit machines, 64-bit code. Unless your huge arrays (such that np*nd>2G) are integer also. Then you’ll get memory requirements really bigger.
Thank you @msz59 , your bi = i*j illustration is indeed great! Thank @Beliavsky too!
I did not realize that will cause an overflow, since bi on the left-hand-side is integer 8, I assume i*j should automatically be integer 8 and is calculated correctly.
But it seems it is not that intelligent and I need to be careful. Probably I may just use integer 8 instead.
A general rule of Fortran is that the RHS of an assignment is computed independently of what is on the LHS and then converted to that type. The product of two default integers is always a default integer.