If I have a c_int8_t
variable in Fortran and want to interpret the underlying bits as an unsigned integer (for indexing rather than for any arithmetic) what is the most efficient way to do the conversion? I want to do something like
X( some_function( my_c_int8_t_var ) ) = 1
where X is an array and some_function
should return a c_int16_t containing the unsigned value of my_c_int8_t_var
. I have seen options including transfer, iadd (or I guess just a simple conditional with a cast and an addition) but I would like to know what would be the most efficient way (this indexing is taking place in an inner loop). Of course it doesn't have to be a function - if it can be done with an inline expression that would be great.
EDIT: It would be nice if the approach would also work for other integer size... ie for getting the contents of unsigned c_int16_t in a c_int32_t and getting an unsigned c_int32_t into a c_int64_t.
You could use transfer()
and ichar()
functions. Something like
X(ichar(transfer(my_c_int8_t_var,"a")))) = 1
For example
use iso_c_binding
write (*,*) ichar(transfer(-1_c_int8_t,"a"))
end
returns 255.
When you cannot find a coresponding character kind (e.g., 16bit) I would write a function that adds huge(1._my_integer_kind) to the value.
integer function indx(i)
integer(c_int16_t),intent(in) :: i
if (i<0) then
indx = 2*(huge(i)+1) + i
else
indx = i
end if
end function indx
or
integer function indx2(i)
integer(c_int8_t),intent(in) :: i
indx2 = TRANSFER([i,0_c_int8_t],1_c_int16_t)
end function indx2
This last case works only for little-endian platforms.
You can make a generic interface to this function.
write (*,*) indx(-2_c_int16_t)
gives 65534