- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
I need to interpret a 2-element integer(4) array as an integer(8) scaler. Currently I'm using
! One of the next two is a dummy argument integer(4) :: pos(2) integer(8) :: cpos cpos = transfer(pos,cpos) ! or pos = transfer(cpos,pos)
These two expressions work as expected but I know from experience that transfer can be slow so I was wondering if there is a nifty trick with pointers I could use instead.
Thanks.
Link Copied
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
You could do it numerically instead:
cpos = pos(1) * 2_8**32 + pos(2)
and:
pos(1) = mod( cpos, 2_8**32 )
pos(2) = cpos / 2_8**32
not as elegant perhaps, but it should not suffer from slowness. If you use the right bit manipulation functions, it could be even faster, I guess.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
For data this small, TRANSFER will be faster than anything else. If you had a lot of data to reinterpret, you can do a "cast" like this:
use, intrinsic :: ISO_C_BINDING integer(8), pointer, dimension(:) :: i8p ... call C_F_POINTER(C_LOC(pos),i8p,[100]) ! i8p now points to the storage of pos as an array of 100 elements
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Well I'm all for keeping things simple so I'll leave this case as transfer. Thanks for the other ideas.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
I forgot - you should put the TARGET attribute on anything you'll be referencing through a pointer.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
You can also use UNION, MAP.
If you do this often, place the map in a user defined type then reference the appropriate mapping via %
Jim Dempsey
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
No, please don't use extensions UNION/MAP unless there is no alternative. Besides, these have to go in a derived type (STRUCTURE/RECORD) which requires significant coding changes based on Simon's request.
Heck, if you're going there, use EQUIVALENCE, but that's not allowed on dummy arguments and is not recommended either.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Simon Geard wrote:
.. I know from experience that transfer can be slow ..
@Simon Geard,
Will it be possible for you to elaborate further on your "transfer can be slow" comment? It is "slow" relative to what? Do you have any performance measures you can share, however qualitative or sketchy, in terms of what you meant by above. For example, for the size of datasets of interest to you, have you compared a similar operation with C union or anything else (perhaps EQUIVALENCE) relative to Fortran TRANSFER and taken stock of some penalty with the TRANSFER option? If so, what is your observation?
Thanks much,
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Steve,
I am aware that the perfectly good UNION is frown upon with code "modernization". IMHO "modernization" is failing if it does not include a means to convienently cast types.
I haven't tried this, but would you happen to know if your "cast" in post #3, when placed in a function, completely inlines to the point were no code is generated? (e.g. no temporary pointer or temporaries)
Jim Dempsey
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Yes, it generates code. But not much, and I would not worry about it unless a performance analysis shows it's a bottleneck.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Here is an example where the use of TRANSFER has no overhead. Compiled with gfortran -O3 -c, the following two versions of a pass-through subroutine yield the same object code (except for the '4'/'8' difference in the subroutine names).
Version A:
subroutine sub4(i4) integer(4) :: i4(2) integer(8) :: i8 ! call sub(transfer(i4,i8)) return end subroutine
Version B:
subroutine sub8(i8) integer(8) :: i8,k8 ! k8=i8 call sub(k8) return end subroutine
- Subscribe to RSS Feed
- Mark Topic as New
- Mark Topic as Read
- Float this Topic for Current User
- Bookmark
- Subscribe
- Printer Friendly Page