Author Message
DanRRight Joined: 10 Mar 2008
Posts: 2774
Location: South Pole, Antarctica Posted: Thu Oct 26, 2023 9:05 am    Post subject: How split 8bytes number into two 4-bytes and combine back Is there some generally used way to split 8-bytes number into two 4-byte ones and then combine these two back to 8-bytes all with minimal efforts?   PaulLaidler Joined: 21 Feb 2005
Posts: 7766
Location: Salford, UK Posted: Thu Oct 26, 2023 10:39 am    Post subject: Code: integer,parameter::k=4  integer(k) v  integer U,L  v = 17_k + ishft(27_k, 32)  print*,v  U = ishft(v, -32)  L = iand(v, Z'00000000ffffffff')  v = int(L,k) + ishft(int(U,k),32)  print*,L,U  print*,v    DanRRight Joined: 10 Mar 2008
Posts: 2774
Location: South Pole, Antarctica Posted: Thu Oct 26, 2023 6:59 pm    Post subject: Thanks Paul, great, that kind of binary trickery I was exactly hoping for.   JohnCampbell

Joined: 16 Feb 2006
Posts: 2502
Location: Sydney Posted: Fri Oct 27, 2023 1:14 am    Post subject: Dan, You can always use EQUIVALENCE, or TRANSFER if you are a modern Fortran dude!   DanRRight Joined: 10 Mar 2008
Posts: 2774
Location: South Pole, Antarctica Posted: Fri Oct 27, 2023 10:55 am    Post subject: Modern Fortran dudes should care about EQUIVALENCE being obsolete in F2018    DanRRight Joined: 10 Mar 2008
Posts: 2774
Location: South Pole, Antarctica Posted: Sat Nov 18, 2023 2:47 pm    Post subject: Paul,

Something is strange here. Let's take integer*8 numbers v larger than approximately 2 billion. After splitting them into pair of U and L and then combining back, these numbers are not getting back into itself

Where i am wrong?

 Code: integer,parameter::k=4  integer(k) v  integer U,L  v = 2222222222_4  print*, v  U = ishft(v, -32)  L = iand(v, Z'00000000ffffffff')  print*,L,U ! getting v back  v = int(L,k) + ishft(int(U,k),32)  print*,v end

By the way how will look this code for v being integer*4 and U and L integer*2 ?   JohnCampbell

Joined: 16 Feb 2006
Posts: 2502
Location: Sydney Posted: Sat Nov 18, 2023 3:07 pm    Post subject: "v = int(L,k)" does not do what you want, but equivalencing v to L,U would.

 Code: integer,parameter::k=4  integer(4) v  integer U,L  common /aa/ L, U  equivalence (v,L)  v = 2222222222_4  print*, v  print*,L,U  U = 0  print*,v  print*,L,U   end

Reminds me of the problem using LOC (aaa) with 32-bit and 3GB memory. I had to write an integer*8 function JLOC to replace calling LOC.   DanRRight Joined: 10 Mar 2008
Posts: 2774
Location: South Pole, Antarctica Posted: Mon Nov 20, 2023 11:41 pm    Post subject: Looks like Paul's code either has an error or its functions have a bug or something is incorrectly used somewhere.

Anyone spotting the error in all that bits manipulations?

For the Integer*4 v the code modified as below works fine
 Code: integer,parameter::k=3  integer v  integer U,L 111 READ(*,*) v  U = ishft(v, -16)  L = iand(v, Z'0000ffff')  print*,L,U ! getting v back  v = int(L,k) + ishft(int(U,k),16)  print*,v  goto 111 end

That allows to use v < 2 billion.
But that limitation on v is a bit too small.

So may be arbitrary precision between INTEGER*4 and INTEGER*8 will work? Because out of the box the U and L these v numbers generate have to be smaller than ~20 million (to be precise - below numbers represented by number of bytes in mantissa of REAL*4 numbers) as i need then to convert integer U and L to real*4 u and l   DanRRight Joined: 10 Mar 2008
Posts: 2774
Location: South Pole, Antarctica Posted: Wed Nov 22, 2023 6:39 am    Post subject: UPDATE,
despite errors with 8byte integers, with smaller v integers like 5 and 6 bytes this still works OK

I think this will work for me: V will be restricted to ~10^15 from 1e9 and paraphrasing Bill Gates "The 10^15 will fit to everyone until AI and Big Data come"

 Code: integer,parameter::k=4  integer(4) v  integer  U,L 111 READ(*,*) v  U = ishft(v, -24)  L = iand(v, Z'000000ffffff')  print*,L,U ! getting v back  v = int(L,k) + ishft(int(U,k),24)  print*,v  goto 111 end

/* V is how many cells or particles you allow in your numerical codes. Of course with integer*8 you can get 10^18 but this will require to increase file sizes twice   PaulLaidler Joined: 21 Feb 2005
Posts: 7766
Location: Salford, UK Posted: Wed Nov 22, 2023 4:13 pm    Post subject: All Fortran integers are signed, so for INTEGER*4 values greater than 2147483647, U and L must be changed to INTEGER*8.

 Code: integer,parameter::k=4  integer(k)::v,U,L  v = 2222222222_k  U = ishft(v, -32)  L = iand(v, Z'00000000ffffffff')  v = int(L,k) + ishft(int(U,k),32)  print*,L,U,v  end    DanRRight Joined: 10 Mar 2008
Posts: 2774
Location: South Pole, Antarctica Posted: Fri Nov 24, 2023 8:12 am    Post subject: Thanks.
But still failing with one more 2...

 Code: integer,parameter::k=4  integer(k)::v,U,L  v = 22222222222_k  U = ishft(v, -32)  L = iand(v, Z'00000000ffffffff')  v = int(L,k) + ishft(int(U,k),32)  print*,L,U,v  end   PaulLaidler Joined: 21 Feb 2005
Posts: 7766
Location: Salford, UK Posted: Fri Nov 24, 2023 8:48 am    Post subject: Code: integer,parameter::k=selected_int_kind(18)  integer(k)::v,U,L  v = 22222222222_k  U = ishft(v, -32)  L = iand(v, Z'00000000ffffffff'_k)  v = ior(L,ishft(U,32))  print*,L,U,v  end    DanRRight Joined: 10 Mar 2008
Posts: 2774
Location: South Pole, Antarctica Posted: Fri Nov 24, 2023 9:42 am    Post subject: Looks like this works! Thanks Paul   Display posts from previous: All Posts1 Day7 Days2 Weeks1 Month3 Months6 Months1 Year Oldest FirstNewest First
 All times are GMT + 1 Hour Page 1 of 1