- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Hi,
I have a subroutine that receives a vector and rearranges its elements according to "mapping" vector. So for example the 1st element becomes 3rd, etc. This is done on integer, double, and double complex vectors. One way to do it is with the generic interface, e.g.:
module mapping_mod
implicit none
interface map
module procedure imap
module procedure dmap
module procedure zmap
end interface map
private
public :: map
contains
subroutine imap (map, in_vector,out_vector)
integer, dimension (:), intent (in) :: map
integer, dimension (:), intent (in) :: in_vector
integer, dimension (:), intent (out) :: out_vector
! do mapping
end subroutine imap
subroutine dmap (map, in_vector,out_vector)
integer, dimension (:), intent (in) :: map
double, dimension (:), intent (in) :: in_vector
double, dimension (:), intent (out) :: out_vector
! do mapping
end subroutine dmap
subroutine zmap (map, in_vector,out_vector)
integer, dimension (:), intent (in) :: map
double complex, dimension (:), intent (in) :: in_vector
double complex, dimension (:), intent (out) :: out_vector
! do mapping
end subroutine zmap
end module mapping_mod
However, the actual mapping procedure needs then to be copy-pasted 3 times. Which is not very elegant. This is not a very complicated example, but there are similar functions in the program much more complicated that follow the same structure (integer, double, complex).
Is there a more elegant way to implement this using a single procedure? Maybe with the use of select type or some other fortran 2003 features?
Thanks in advance,
Petros
Link Copied
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
One way to do this is to use an include file. That contains the body of the routine and then you only need to provide the correct declarations.
By splitting the code into three (or more) modules, one for each type, and then defining an overall module to unite them all again, you can actually keep the routine names independent of the type. Various other methods are also possible, but unfortunately none really "trivial". On the comp.lang.fortran newsgroup there are currently a number of related discussions.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
or keep imap dmap zmap that all call one further routine routine that does all the work for all cases maybe with optional args or a flag on the call to say which of the three args is to be used.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
The Select/Type would have the same issue of redundant (copy/paste) of the code. The suggestion of using an include file is good with which you have the choice of using either the Fortran INCLUDE or the Fortran PreProcessor #include. Both work, the FPP gives you additional flexibility such as defining macros.
A third alternative you have (which I haven't used) is BlockIt (http://fortranwiki.org/fortran/show/BlockIt). With BlockIt, you can introduce a type of template capability. This is done as a Pyhthon PreProcessor. You will have to install Python as well as the Blockit scripts.
Jim Dempsey
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
As Arjen Markus mentioned, there are some ongoing discussions along these lines at comp,lang.fortran, in particular this one:
https://groups.google.com/forum/#!topic/comp.lang.fortran/R_zBfQKmcHE
I suggest you post your question as well as need in the above thread as it appears to garner the attention of those closer to Fortran standards development. Who knows, something good might come out of it in terms of standard, elegant, and convenient features in the language to support such coding needs.
Separately, if you're ok with the idea of using include files (I personally prefer not to use them) and/or with some neat tricks with modules shown by Arjen Markus in the above c.l.f. thread, you may want to look into the parameterized derived type facility in Fortran 2003, now being supported to an improving extent in Intel Fortran. Here's a recent thread on it where you can see some working examples, especially in message #10:
https://software.intel.com/en-us/forums/intel-fortran-compiler-for-linux-and-mac-os-x/topic/585069
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
There is a post in the clf thread linked in Quote #5 that uses implicit typing and include to propagate a template procedure to procedures using multiple types. That's probably what you need in the general case because the stuff with select type still seems to require multiple copies of the code to be pasted in anyway as mentioned in Quote #4. BTW, don't mix #include with include: they are completely different and #include, in particular, just breaks Fortran code. Fortran doesn't need the C preprocessor stuff to the extent that C does because it provides such a richness of possibilities with its constant expressions and specification expressions.
Of course the example referred to in Quote #5 blows up ifort and since Steve seems to have been placed on IR, designated to return after that sack that broke his clavicle at the last j3 meeting so he will be out for 8 weeks and nobody from Intel seems to be monitoring that forum, that issue may not get addressed quickly. However, it seems that the syntax that blew up ifort is not essential for the technique used in the example, so it's probably OK to adapt it to your needs.
In the instant case, however, what about
out_vector(map) = in_vector
which is so simple that it needs no procedure invocation.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Hi people, thanks for the amazing comments.
I know about the include, but I was thinking about something more elegant. The problem with include is that the file is not part of my project and kind of feels like an "appendix". Same with blockit, I would like to stick with standard fortran...
@app4619 : calling another procedure with optional arguments is a nice idea, but I think it will complicate things. And internally I would still need to duplicate code...
@arjenmarkus : I didn't really understand the modules trick. I'll look through the newsgroup to see what exactly you mean. But again, the idea was to make it simpler, that sounds a bit over-complicating.
@FortranFan : Nice thread, I'll go through it more carefully. I'm not very comfortable with class and select type, I should get updated...
@Repeat Offender :
out_vector(map) = in_vector
I didn't know you can do that in fortran, really. I will for sure keep that in mind. However, some elements are mapped to the same place, and these should be added together. I believe the above one-liner will not do that, yes?
- Subscribe to RSS Feed
- Mark Topic as New
- Mark Topic as Read
- Float this Topic for Current User
- Bookmark
- Subscribe
- Printer Friendly Page