Wednesday 10 December 2008

Addressing integer bits in Fortran

I want to find out about 8-bit integers (kind = 1) in gfortran.
Apparently they seem to be signed and stored as "two's complement". When you give the integer a value, you can view the bits like so:

integer(kind = 1) I
integer numbit(8) ! stores the bit values as 0 or 1's

I = 5
do j= 1,8
numbit(i) = ibits(I,j-1,1)
enddo
write(*,*) 'bits: ', numbit

...where here IBITS is extracting 1 bit from I at position j-1 and returning it as an integer with the bit value right-justified and the rest of the bits 0. So "1" at position j-1 is returned by ibits(I,j-1,1) as "00000001" which has integer value 1.

Alternatively, I could do this:

integer(kind = 1) I
integer numbit(8) ! stores the bit values as 0 or 1's

I = 5
do j= 1,8
numbit(i) = btest(I,j-1)
enddo
write(*,*) 'bits: ', numbit

...where BTEST returns .true. if the bit in position j-1 is "1", and .false. otherwise. This is implicitly converted to an integer by the gfortran compiler (but not without warnings at compile time), where .true. => 1 and .false. => 0.

Both of these return:
bits: 1 0 1 0 0 0 0 0

I guess the take-home message is that when you write out a bit-string, eg.
5 = [0101]
then the right-most bit is addressed as bit 0, and in general, bit number 1 is the second bit as you move left, etc.

So if you start with all bits set to zero, you can use IBSET to set certain bits to 1 and get whatever number you fancy...

I = 0 ! [00000000]
I = ibset(I,0) ! [00000001]
I = ibset(I,2) ! [00000101]
write(*,*) 'I = ', I

... and we get I = 5, as intended.

I guess this is a stupid post, but it wasn't obvious to me that the bit string would be numbered from the right starting at index 0. The default index for matrices in Fortran 95 starts at 1. Ho hum.

No comments: