|
forums.silverfrost.com Welcome to the Silverfrost forums
|
View previous topic :: View next topic |
Author |
Message |
DanRRight
Joined: 10 Mar 2008 Posts: 2866 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? |
|
Back to top |
|
|
PaulLaidler Site Admin
Joined: 21 Feb 2005 Posts: 8017 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
|
|
|
Back to top |
|
|
DanRRight
Joined: 10 Mar 2008 Posts: 2866 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. |
|
Back to top |
|
|
JohnCampbell
Joined: 16 Feb 2006 Posts: 2584 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! |
|
Back to top |
|
|
DanRRight
Joined: 10 Mar 2008 Posts: 2866 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 |
|
Back to top |
|
|
DanRRight
Joined: 10 Mar 2008 Posts: 2866 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 ? |
|
Back to top |
|
|
JohnCampbell
Joined: 16 Feb 2006 Posts: 2584 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. |
|
Back to top |
|
|
DanRRight
Joined: 10 Mar 2008 Posts: 2866 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 |
|
Back to top |
|
|
DanRRight
Joined: 10 Mar 2008 Posts: 2866 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 |
|
Back to top |
|
|
PaulLaidler Site Admin
Joined: 21 Feb 2005 Posts: 8017 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 |
|
|
Back to top |
|
|
DanRRight
Joined: 10 Mar 2008 Posts: 2866 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 |
|
|
Back to top |
|
|
PaulLaidler Site Admin
Joined: 21 Feb 2005 Posts: 8017 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
|
|
|
Back to top |
|
|
DanRRight
Joined: 10 Mar 2008 Posts: 2866 Location: South Pole, Antarctica
|
Posted: Fri Nov 24, 2023 9:42 am Post subject: |
|
|
Looks like this works! Thanks Paul |
|
Back to top |
|
|
|
|
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
|