# Moving Bits Question

**URL:** <https://fortran-lang.discourse.group/t/moving-bits-question/4799>\
**Category:** Help\
**Created:** [November 24, 2022, 6:44pm UTC](https://fortran-lang.discourse.group/t/moving-bits-question/4799 "2022-11-24T18:44:21Z")\
**Posts on this page:** 1\
**Showing post:** 9

<div class="post-metadata">

**Author:** ![FortranFan](https://avatars.discourse-cdn.com/v4/letter/f/96bed5/32.png) [@FortranFan](https://fortran-lang.discourse.group/u/FortranFan)\
**Post date:** [November 24, 2022, 9:36pm UTC](https://fortran-lang.discourse.group/t/moving-bits-question/4799/9 "2022-11-24T21:36:25Z")

</div>

> [@RonShepard](#):
>
> … I have individual integers. I want to store them in a bit bucket (an int64 array). And then I want to be able to retrieve or modify an individual value from that bit bucket. If I could control where the bits go into each int64 element (or elements, when they cross boundaries), then I could avoid any endian issues. …

> [@RonShepard](#):
>
> Is a loop over the individual bits really the best that fortran has to offer?

@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?

```fortran
! 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

```

```auto
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>

```

---

_[View the full topic](https://fortran-lang.discourse.group/t/moving-bits-question/4799)._
