Search code examples
fortranintel-fortran

How to get low word and high word from a real?


For data type 32bit reals in fortran, how could you move the first and last 16 bits into integer values? I've tried a number of methods, but can only figure this out if the input is of integer type. Fortran seems to have a limitation working with real types.

example:

decimal 1.0 in binary is : 0011 1111 1000 0000 0000 0000 0000 0000

set HIGH_WORD = 0011 1111 1000 0000

set LOW_WORD = 0000 0000 0000 0000

SUBROUTINE TEST(INPUT, LOW, HIGH)

REAL*4 INPUT
INTEGER*4 LOW
INTEGER*4 LOW_MASK
INTEGER*4 HIGH
INTEGER*4 HIGH_MASK


! METHOD1: ONLY WORKS ON INTS
HIGH = IBITS(INPUT, 0, 16)
LOW = IBITS(INPUT, 16, 16)

! METHOD2: ALSO ONLY WORKS ON INTS
LOW_MASK = 65535
HIGH_MASK = -65536
LOW = LOW_MASK.AND.IN
HIGH = HIGH_MASK.AND.IN
HIGH = JISHFT(HIGH, -16)

END


Solution

  • The TRANSFER intrinsic transfers physical representation:

      use, intrinsic :: iso_fortran_env, only : real32, int16
    
      implicit none
    
      integer(int16) :: integer(2)
      real(real32) :: real
    
      real = 1.0_real32
      integer = transfer(real, integer)
    
      print '(B32.32)', real
      print '(B16.16)', integer
    end
    

    Transferring of physical representation can include, as in this case, carving a scalar up into smaller individual array elements.