How to convert from one Fortran integer kind to a smaller one?

I need to convert a parameter from integer(kind=8) to integer(kind=4) in Fortran, is there any (simple) way of doing this?

This parameter is an input number, and if this number is greater than 2^31-1 (the limit of a 4-byte integer), the program will always ask for a smaller number (so it can "fit" inside those 4 bytes), so I think that this shouldn't be a problem.


Solution 1:

To create integer of any kind use

result = int(source, kind=result_kind)

so you can do

result = int(source, 4)

source can be any number, including an integer of any kind.

Note that kind=8 does not mean 8 bytes and kind=4 does not mean 4 bytes. There are compilers which do not have kinds 4 and 8 at all. These numbers are not portable. Do not use them. See Fortran: integer*4 vs integer(4) vs integer(kind=4) for more details.

Solution 2:

As Vladimir F's answer notes, the intrinsic function int returns an integer value of desired kind int(i,kind=kind).

When an expression of a certain kind is required (such as in a procedure argument list) this is quite useful:

call sub_with_int_i1_arg(INT(int_i2, kind=i1))

However, intrinsic assignment to an integer already provides conversion if required:

  integer, parameter :: kind1=7, kind2=23
  integer(kind1) :: i
  integer(kind2) :: j = 85

! The intrinsic assignment
  i = j
! is equivalent to
  i = INT(j,KIND(i))
! which here is also
  i = INT(j,kind1)
end

The intrinsic huge may be useful in determining whether the range of i is large enough:

if (ABS(j).le.HUGE(i)) then
  i = j
else
  error stop "Oh noes :("
end if

As Steve Lionel commented about the draft, Fortran 2018 introduced the intrinsic function out_of_range which also tests such cases:

if (.not.OUT_OF_RANGE(j,i)) then
  i = j
else
  error stop "Oh noes :("
end if

However, even in early 2022 it's not wise to rely on implementation of this function.