forums.silverfrost.com
Welcome to the Silverfrost forums

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
Site Admin

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
Site Admin

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
Site Admin

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

 Jump to: Select a forum Admin----------------Announcements FTN95----------------GeneralKBaseSupportSuggestionsClearWin+Plato64-bit FTN77----------------Support
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum

Powered by phpBB © 2001, 2005 phpBB Group