0

I have a memory-critical FORTRAN program, which at the moment uses two integer arrays, the first uses 4 BYTES integers and the second uses 1 BYTE integers.

Neither array is "fully" used, i.e. I know that the number stored in the 4 byte array won't exceed a million or so (so I need more than 2 bytes, but I'm not using all the bits of 4 bytes) and likewise I only use 2 bits of the 1-byte array as "flags".

To save memory I wanted to try and combine the two, i.e. use the two left-most bits of the 4-byte array to store the 2 flags.

Now I know if I set the INTEGER value first, I can subsequently set the flags using IBSET/IBCLR, and still extract my integer safely using the IBITS function to extract the rightmost X bits (X=28 in this case):

integer(kind=4) :: imark,inum 

imark=600245 ! example number 

! use bits 29 and 30 to store flags...
imark=IBSET(imark,29) 
imark=IBSET(imark,30)

print *,imark ! gives 1611212981

! extract right most bits:
inum=IBITS(imark,0,28)
print *,inum  ! gives back 600245 as desired.

However, I don't know how to modify the integer, while retaining the memory of the flags. In other words, I need the opposite function to IBITS, to copy an integer assigning only the X rightmost bits.

Obviously if I assign an new integer value (imark=343525) it will reset the flag bits. I could write a function that cycles through the rightmost X bits of the new integer value one at a time and then sets them using IBSET/IBCLR in my 4-byte array, but that seems very long-winded. But I do not find any intrinsic function to perform this task.

ClimateUnboxed
  • 7,106
  • 3
  • 41
  • 86
  • 1
    Note that kind=4 does not have to mean 4 bytes. It does not have to be available at all. I know at least two compilers which behave this way. Read https://stackoverflow.com/questions/3170239/fortran-integer4-vs-integer4-vs-integerkind-4 – Vladimir F Героям слава Aug 09 '17 at 14:41
  • 1
    How about masking off unwanted bits by AND() ? – tim18 Aug 09 '17 at 14:43
  • good point Vladamir, question edited for clarity - thanks! @tim17, how would you do this? would you still need to cycle through the bits? – ClimateUnboxed Aug 09 '17 at 14:53
  • 2
    BTW this approach sounds really frightening. These tricks were done in the 70s and 80s when the memory was very small and fixed. Today's you can easily buy more memory or use more nodes of a supercomputer. This development and maintenance can easily cost more than a larger computer. – Vladimir F Героям слава Aug 09 '17 at 14:54
  • There is no INTEGER(KIND=C_INT24_t), but one could make a TYPE of 3 bytes and then shuffle those bit into an INTEGER(KIND=C_INT32_t) for processing and later shove those back into memory as the 24-bit TYPE that you define... – Holmz Aug 10 '17 at 07:36
  • @VladimirF - I spent my early teens cramming assembly language code into 41 K on a ZX Spectrum (sigh) hence my bad habits ;-) Thanks for the solution, was perfect! – ClimateUnboxed Aug 10 '17 at 09:12

1 Answers1

5

There is intrinsic function merge_bits(i, j, mask) in Fortran 2008. It merges the bits from two integers according to a logical mask.

You must prepare a logical mask as an integer which has ones in the first two bits and zeros elsewhere (or the opposite one).