@RonShepard and any other readers interested in something like this,
Please consider working with stdlib
and introducing some general facilities in there that all the Fortran practitioners can make use of.
Also, avoid copying data as much as possible in such a facility.
In addition to the bitsets module I suggested upthread, if something additional is required for a specific need, here is another custom type to consider as merely a crude starting point. Based on a “NY minute” worth of thought, methinks the fields in such a “bucket” should be the length of a colloquial “byte” i.e., 8 bits. Further insight might change this thinking. Anyways, here it is: how is it for the “best” Fortran has to offer, does this pass muster?
! File p.f90
module bitbucket_m
use, intrinsic :: iso_c_binding, only : I1 => c_int8_t, I4 => c_int32_t, I8 => c_int64_t, c_loc, &
c_f_pointer
private
type, public :: bitbucket_t
! Field of 8-bit integers
private
integer(I1) :: m_fields(8) = 0_i1
contains
private
procedure, pass(this) :: zap_fields
procedure, pass(this), public :: int32 => get_int32
procedure, pass(this), public :: int64 => get_int64
generic, public :: zap => zap_fields
end type bitbucket_t
type :: pos_t
integer :: pos = 0
end type
type(pos_t), public, parameter :: POS0 = pos_t()
type(pos_t), public, parameter :: POS32 = pos_t( pos=32 )
contains
subroutine zap_fields( this, idx )
! Argument list
class(bitbucket_t), intent(inout) :: this
integer, intent(in) :: idx(:)
! Local variable
this%m_fields( idx ) = 0_i1
return
end subroutine zap_fields
function get_int32( this, pos ) result(pvals)
! Argument list
class(bitbucket_t), intent(in), target :: this
type(pos_t), intent(in) :: pos
! Function result
integer(I4), pointer :: pvals
pvals => null()
select case ( pos%pos )
case ( 0 )
call c_f_pointer( cptr=c_loc(this%m_fields(1)), fptr=pvals )
case ( 32 )
call c_f_pointer( cptr=c_loc(this%m_fields(3)), fptr=pvals )
end select
return
end function get_int32
function get_int64( this ) result(pval)
! Argument list
class(bitbucket_t), intent(in), target :: this
! Function result
integer(I8), pointer :: pval
call c_f_pointer( cptr=c_loc(this%m_fields), fptr=pval )
return
end function get_int64
end module
use, intrinsic :: iso_fortran_env, only : int32, int64
block
integer(int32) :: i32
integer(int64) :: i64
print *, "Block 1: using copy assignment with a type conversion function"
i32 = -123456
i64 = bit32_to_64( i32 )
print "(*(g0))", "i32 = ", i32
print "(*(g0))", "i64 = ", i64
print "(g0,b0)", "i32 (bit pattern): ", i32
print "(g0,b64)","i64 (bit pattern): ", i64
end block
print *
block
use bitbucket_m, only : bitbucket_t, POS0
type(bitbucket_t) :: bucket
print *, "Block 2: using a custom type"
bucket%int32( POS0 ) = -123456
print "(*(g0))", "bucket%int32( POS0 ) = ", bucket%int32( POS0 )
print "(*(g0))", "bucket%int64() = ", bucket%int64()
print "(g0,b0)", "bucket%int32( POS0 ) (bit pattern): ", bucket%int32( POS0 )
print "(g0,b64)","bucket%int64() (bit pattern): ", bucket%int64()
end block
contains
! copy an int32 to the first 32 bits of an int64
elemental integer(int64) function bit32_to_64(i32) result(i64)
integer(int32), intent(in) :: i32
integer :: bit
i64 = 0
do bit=0,31
i64 = merge(ibset(i64,bit),ibclr(i64,bit),btest(i32,bit))
end do
end function
end
C:\temp>gfortran -Wall p.f90 -o p.exe
C:\temp>p.exe
Block 1: using copy assignment with a type conversion function
i32 = -123456
i64 = 4294843840
i32 (bit pattern): 11111111111111100001110111000000
i64 (bit pattern): 11111111111111100001110111000000
Block 2: using a custom type
bucket%int32( POS0 ) = -123456
bucket%int64() = 4294843840
bucket%int32( POS0 ) (bit pattern): 11111111111111100001110111000000
bucket%int64() (bit pattern): 11111111111111100001110111000000
C:\temp>