forums.silverfrost.com Forum Index forums.silverfrost.com
Welcome to the Silverfrost forums
 
 FAQFAQ   SearchSearch   MemberlistMemberlist   UsergroupsUsergroups   RegisterRegister 
 ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

How split 8bytes number into two 4-bytes and combine back

 
Post new topic   Reply to topic    forums.silverfrost.com Forum Index -> General
View previous topic :: View next topic  
Author Message
DanRRight



Joined: 10 Mar 2008
Posts: 2817
Location: South Pole, Antarctica

PostPosted: Thu Oct 26, 2023 9:05 am    Post subject: How split 8bytes number into two 4-bytes and combine back Reply with quote

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?
Back to top
View user's profile Send private message
PaulLaidler
Site Admin


Joined: 21 Feb 2005
Posts: 7926
Location: Salford, UK

PostPosted: Thu Oct 26, 2023 10:39 am    Post subject: Reply with quote

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
Back to top
View user's profile Send private message AIM Address
DanRRight



Joined: 10 Mar 2008
Posts: 2817
Location: South Pole, Antarctica

PostPosted: Thu Oct 26, 2023 6:59 pm    Post subject: Reply with quote

Thanks Paul, great, that kind of binary trickery I was exactly hoping for.
Back to top
View user's profile Send private message
JohnCampbell



Joined: 16 Feb 2006
Posts: 2554
Location: Sydney

PostPosted: Fri Oct 27, 2023 1:14 am    Post subject: Reply with quote

Dan, You can always use EQUIVALENCE, or TRANSFER if you are a modern Fortran dude!
Back to top
View user's profile Send private message
DanRRight



Joined: 10 Mar 2008
Posts: 2817
Location: South Pole, Antarctica

PostPosted: Fri Oct 27, 2023 10:55 am    Post subject: Reply with quote

Modern Fortran dudes should care about EQUIVALENCE being obsolete in F2018 Smile
Back to top
View user's profile Send private message
DanRRight



Joined: 10 Mar 2008
Posts: 2817
Location: South Pole, Antarctica

PostPosted: Sat Nov 18, 2023 2:47 pm    Post subject: Reply with quote

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 ?
Back to top
View user's profile Send private message
JohnCampbell



Joined: 16 Feb 2006
Posts: 2554
Location: Sydney

PostPosted: Sat Nov 18, 2023 3:07 pm    Post subject: Reply with quote

"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.
Back to top
View user's profile Send private message
DanRRight



Joined: 10 Mar 2008
Posts: 2817
Location: South Pole, Antarctica

PostPosted: Mon Nov 20, 2023 11:41 pm    Post subject: Reply with quote

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
Back to top
View user's profile Send private message
DanRRight



Joined: 10 Mar 2008
Posts: 2817
Location: South Pole, Antarctica

PostPosted: Wed Nov 22, 2023 6:39 am    Post subject: Reply with quote

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
Back to top
View user's profile Send private message
PaulLaidler
Site Admin


Joined: 21 Feb 2005
Posts: 7926
Location: Salford, UK

PostPosted: Wed Nov 22, 2023 4:13 pm    Post subject: Reply with quote

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
Back to top
View user's profile Send private message AIM Address
DanRRight



Joined: 10 Mar 2008
Posts: 2817
Location: South Pole, Antarctica

PostPosted: Fri Nov 24, 2023 8:12 am    Post subject: Reply with quote

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
Back to top
View user's profile Send private message
PaulLaidler
Site Admin


Joined: 21 Feb 2005
Posts: 7926
Location: Salford, UK

PostPosted: Fri Nov 24, 2023 8:48 am    Post subject: Reply with quote

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
Back to top
View user's profile Send private message AIM Address
DanRRight



Joined: 10 Mar 2008
Posts: 2817
Location: South Pole, Antarctica

PostPosted: Fri Nov 24, 2023 9:42 am    Post subject: Reply with quote

Looks like this works! Thanks Paul
Back to top
View user's profile Send private message
Display posts from previous:   
Post new topic   Reply to topic    forums.silverfrost.com Forum Index -> General All times are GMT + 1 Hour
Page 1 of 1

 
Jump to:  
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