Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

procedures with "generic kind" dummy arguments

141 views
Skip to first unread message

Stefano Zaghi

unread,
Oct 22, 2012, 11:00:02 AM10/22/12
to
Hi all,
I would like to write procedures (functions and subroutines) that "mime" the behavior of some internal procedures like sin(x), cos(x)...

For these family of internal procedures the dummy argument "x" can be real or complex with any kind and the result is of the same kind of "x". The attention (for me) is focused on the precision of the operation (kind) performed and on its efficiency.

Up to now I obtain this behavior by means of the dynamic dispatching ability with a generic interface and programming each procedure for each different kind, e.g.

interface foo
module procedure foo_R8,foo_R4
endinterface

function foo_R8(x) result(foo)
...
real(8):: x
real(8):: foo
...
endfunction foo_R8

function foo_R4(x) result(foo)
...
real(4):: x
real(4):: foo
...
endfunction foo_R4

Is it possible to avoid to rewrite the same code for each procedure of different kind? It is boring, errors prone and I am not sure of the efficiency of dynamic dispatching. Note that I intensively use this approach with derived type.

Maybe the new polymorphic abilities of F2003 could help me. For example using class(*) for x argument can I avoid the dynamic dispatching?. But what about the efficiency of this polymorphic approach?

Thanks for suggestions.

Sincerely

Ron Shepard

unread,
Oct 22, 2012, 11:22:09 AM10/22/12
to
In article <554f6e3c-79d9-46f3...@googlegroups.com>,
Stefano Zaghi <stefan...@gmail.com> wrote:

> Is it possible to avoid to rewrite the same code for each procedure of
> different kind? It is boring, errors prone and I am not sure of the
> efficiency of dynamic dispatching. Note that I intensively use this approach
> with derived type.

I've seen two approaches. One is simply to use the INCLUDE to
reference a file with the redundant code. After all of the
appropriate declarations, the INCLUDE inserts the code that uses
those variables to compute the results.

The second approach takes this a step further. It uses a macro
processor to loop over a list of separate declarations, and each
iteration of the loop outputs one of the subroutines. Basically you
write a program that writes the code, so you are one step of
abstraction away from the fortran code itself. There are several
macro processors that I've seen used, including m4, awk, perl,
filepp <http://www.cabaret.demon.co.uk/filepp>, and even shell
scripts. If you are starting from scratch, then filepp might be the
best starting point because it is already designed more or less to
be a language preprocessor.

$.02 -Ron Shepard

ken.fa...@gmail.com

unread,
Oct 22, 2012, 1:47:22 PM10/22/12
to
On Monday, October 22, 2012 8:22:13 AM UTC-7, Ron Shepard wrote:
> In article <554f6e3c-79d9-46f3...@googlegroups.com>,
>
> Stefano Zaghi <stefan...@somwhere.com> wrote:
>
> > Is it possible to avoid to rewrite the same code for each procedure of
> > different kind? It is boring, errors prone and I am not sure of the
> > efficiency of dynamic dispatching. Note that I intensively use this approach
> > with derived type.
>
> I've seen two approaches. One is simply to use the INCLUDE to
> reference a file with the redundant code. After all of the
> appropriate declarations, the INCLUDE inserts the code that uses
> those variables to compute the results.
[...]

And for this approach, search the comp.lang.fortran archives for
any of the many posts by James van Buskirk which demonstrate this
method. In fact, it sort seems to me he *invented* this method!
Although I suppose others could/would have come to the same thing
independently. ;-)

-Ken

Robin Vowels

unread,
Oct 22, 2012, 9:57:40 PM10/22/12
to
On Oct 23, 4:47 am, ken.fairfi...@gmail.com wrote:
> On Monday, October 22, 2012 8:22:13 AM UTC-7, Ron Shepard wrote:
> > In article <554f6e3c-79d9-46f3...@googlegroups.com>,
>
> >  Stefano Zaghi <stefano.za...@somwhere.com> wrote:
>
> > > Is it possible to avoid to rewrite the same code for each procedure of
> > > different kind? It is boring, errors prone and I am not sure of the
> > > efficiency of dynamic dispatching. Note that I intensively use this approach
> > > with derived type.
>
> > I've seen two approaches.  One is simply to use the INCLUDE to
> > reference a file with the redundant code.  After all of the
> > appropriate declarations, the INCLUDE inserts the code that uses
> > those variables to compute the results.

>
> And for this approach, search the comp.lang.fortran archives for
> any of the many posts by James van Buskirk which demonstrate this
> method.  In fact, it sort seems to me he *invented* this method!
> Although I suppose others could/would have come to the same thing
> independently. ;-)

It's unlikely that he "invented" this method.
INCLUDE had been in Fortran since F90,
and in F77 in an earlier form.
However, user-written generic procedures have been available
in Fortran only since F90.

INCLUDE had been available in PL/I since 1966 for this and
many other purposes, along with a macro pre-processor,
both of which are suitable for preparing generic procedures.

glen herrmannsfeldt

unread,
Oct 22, 2012, 11:56:30 PM10/22/12
to
Robin Vowels <robin....@gmail.com> wrote:
> On Oct 23, 4:47�am, ken.fairfi...@gmail.com wrote:

(snip previously discussing a method for generating generic
functions for different KINDs.)

>> And for this approach, search the comp.lang.fortran archives for
>> any of the many posts by James van Buskirk which demonstrate this
>> method. �In fact, it sort seems to me he *invented* this method!
>> Although I suppose others could/would have come to the same thing
>> independently. ;-)

> It's unlikely that he "invented" this method.

Yes, he might not have invented it, but it does look like
he tested it out more than others.

> INCLUDE had been in Fortran since F90,
> and in F77 in an earlier form.
> However, user-written generic procedures have been available
> in Fortran only since F90.

> INCLUDE had been available in PL/I since 1966 for this and
> many other purposes, along with a macro pre-processor,
> both of which are suitable for preparing generic procedures.

Yes the PL/I preprocessor should make this much easier.

Maybe it is there now, but last I knew, and definitely
in 1966, PL/I didn't have user generic functions.

You should be able to generate a series of functions
with different names using a %DO loop.

Last I knew, the PL/I preprocessor only has integer variables
(FIXED DEC(5,0) if I remember right) so it would not be so
easy to generate the constants that some functions might
require. You could, though, select between some
precomputed constants.

-- glen
Message has been deleted

Robin Vowels

unread,
Oct 23, 2012, 2:15:53 AM10/23/12
to
On Oct 23, 2:56 pm, glen herrmannsfeldt <g...@ugcs.caltech.edu> wrote:

> Maybe it is there now, but last I knew, and definitely
> in 1966, PL/I didn't have user generic functions.

What does the PL/I keyword GENERIC convey to you?

The PL/I Language Reference Manual C28-8201-1 (1968)
describes the facility in the PL/I-F compiler.

Generic procedures (including functions) have been part of the
PL/I language since 1966.

> You should be able to generate a series of functions
> with different names using a %DO loop.

> Last I knew, the PL/I preprocessor only has integer variables
> (FIXED DEC(5,0) if I remember right)

PL/I preprocessor has CHARACTER and FIXED variables.
In current IBM compilers, the preprocessor supports numeric
variables having either five decimal digits or 31 binary digits.

> so it would not be so
> easy to generate the constants that some functions might
> require. You could, though, select between some
> precomputed constants.

Any constant can be generated by the PL/I preprocessor.

Stefano Zaghi

unread,
Oct 23, 2012, 3:34:31 AM10/23/12
to
Dear all,

thank you very much for your help.

I already know the option of "include-trick" (and the help of preprocessors), but I would like to completely avoid the necessity of many different procedures for many different kinds (of dummy arguments). I think that I must be more explicit. The question can be formulated as following. Suppose you have an overloaded operator like the following:

interface operator (*)
module procedure vec_mul_vec
module procedure ScalR8P_mul_vec
module procedure ScalR4P_mul_vec
module procedure ScalI8P_mul_vec
module procedure ScalI4P_mul_vec
module procedure ScalI2P_mul_vec
module procedure ScalI1P_mul_vec
module procedure vec_mul_ScalR8P
module procedure vec_mul_ScalR4P
module procedure vec_mul_ScalI8P
module procedure vec_mul_ScalI4P
module procedure vec_mul_ScalI2P
module procedure vec_mul_ScalI1P
endinterface

Note that vec is a derived type and "Scal" is a numerical dummy argument (for this case it could be only integer or real).

This generic interface uses the dynamic dispatching to perform the following multiplications:

...
vec2 = 1.3_R4P * vec1
vec3 = vec2 / 3_I8P
...

The programmer must write each procedure of the above generic interface for each different variable type and kind (for case I have considered there are 13 different procedures), that are similar to:

elemental function vec_mul_ScalI4P(vec,scal) result(mul)
implicit none
type(Type_Vector), intent(IN):: vec
integer(I4P), intent(IN):: scal
type(Type_Vector):: mul

mul%x = real(scal,R_P) * vec%x
mul%y = real(scal,R_P) * vec%y
mul%z = real(scal,R_P) * vec%z
return
endfunction vec_mul_ScalI4P

I am wondering if, using the new class(*) polymorphic feature of F03, is it possible to substitute the 13 different procedures with fewer ones like the following:

elemental function vec_mul_scal(vec,scal) result(mul)
implicit none
type(Type_Vector), intent(IN):: vec
class(*), intent(IN):: scal
type(Type_Vector):: mul

mul%x = real(scal,R_P) * vec%x
mul%y = real(scal,R_P) * vec%y
mul%z = real(scal,R_P) * vec%z
return
endfunction vec_mul_scal

Can the above "class(*)-type" procedure substitute all the 6 procedures vec_mul_ScalR8P, vec_mul_ScalR4P, vec_mul_ScalI8P, vec_mul_ScalI4P, vec_mul_ScalI2P, vec_mul_ScalI1P?

If it is possible instead of 13 different procedures I have to write only 3 procedures to complete my overloaded operator...

And if it is possible what about the efficiency of "class(*)" statement? I am not completely sure of the efficiency of dynamic dispatching of the 13 procedures currently used, but it seems that the overhead is not so high.

Thank you again.


Stefano Zaghi

unread,
Oct 24, 2012, 4:11:37 AM10/24/12
to
Hi all,
I have found a solution, but I think it is bad the original dynamic dispatching with generic interface.

The above unlimited polymorphic function works ONLY with the following changes:

elemental function vec_mul_scal(vec,scal) result(mul)
implicit none
type(Type_Vector), intent(IN):: vec
class(*), intent(IN):: scal
type(Type_Vector):: mul

select type(scal)
type is (integer)
mul%x = real(scal,R_P) * vec%x
mul%y = real(scal,R_P) * vec%y
mul%z = real(scal,R_P) * vec%z
type is (real)
mul%x = real(scal,R_P) * vec%x
mul%y = real(scal,R_P) * vec%y
mul%z = real(scal,R_P) * vec%z
end select
return
endfunction vec_mul_scal

We still have 1 function instead of 6 different ones, but now there is the necessity of a "select type" control flow.

The question is: is the last unlimited polymorphic function more or less efficient than the original generic interface to the 6 functions?

Thanks to all.

Rafik Zurob

unread,
Oct 24, 2012, 5:54:30 AM10/24/12
to
Hi

Generic interface blocks (as described in your original post) don't use
dynamic dispatch. The rules for generic interface blocks ensure that the
compiler is always able to resolve the generic interface to a specific
procedure call at compile time. So there is no performance penalty at all.

What you have below with unlimited polymorphic, as you noted, requires
select type. Determining the type is done at run time and will incur a
performance penalty. In addition, class(*) is often implemented using
descriptors (aka dope vectors). So when you pass an integer or real actual
argument corresponding to "scal", the compiler has to construct a descriptor
at the call site. Finally, class(*) has aliasing implications that also add
to the performance penalty.

So if your main concern is efficiency, the generic interface blocks you had
originally are the best. One way to reduce repetition is by using the
preprocessor as previously suggested in this thread. Another way is to
write some utility procedures and implement the various specific procedures
in the generic interface in terms of those utilities. If you do this, turn
on the inlining facilities of your compiler to inline the utility
procedures.

Regards

Rafik
Visit the Fortran Cafe at
https://www.ibm.com/developerworks/mydeveloperworks/groups/service/html/communityview?communityUuid=b10932b4-0edd-4e61-89f2-6e478ccba9aa

"Stefano Zaghi" <stefan...@gmail.com> wrote in message
news:310b5800-a13d-43f7...@googlegroups.com...

Wolfgang Kilian

unread,
Oct 24, 2012, 5:57:21 AM10/24/12
to
In theory, dynamic dispatching for the polymorphic function is done at
runtime, once per call. The generic interface, as the more traditional
alternative, amounts to 'static' dispatching, i.e., one of the specifics
is inserted already at compile time. At runtime, no dispatching is
necessary.

In practice, it depends on the compiler and optimization. The important
difference is probably not the decision that is necessary for dynamic
dispatching, but the layout in memory. I don't think there will be a
noticeable difference in the case at hand, but this can only be answered
by compiler writers (or by a measurement, of course).

-- Wolfgang



--
E-mail: firstnameini...@domain.de
Domain: yahoo

Stefano Zaghi

unread,
Oct 24, 2012, 6:11:21 AM10/24/12
to
Dear Rafik, thank you very much.

> Hi
> Generic interface blocks (as described in your original post) don't use
> dynamic dispatch. The rules for generic interface blocks ensure that the
> compiler is always able to resolve the generic interface to a specific
> procedure call at compile time. So there is no performance penalty at all.

Wow... I am totally wrong.
I have supposed that the generic interface resolves the callings at run-time by means of the dynamic dispatching... but this is not sense, now I am thinking to that. You are right: the generic interface resolves the callings at compile time without performances penalty. Thank you!

> What you have below with unlimited polymorphic, as you noted, requires
> select type. Determining the type is done at run time and will incur a
> performance penalty. In addition, class(*) is often implemented using
> descriptors (aka dope vectors). So when you pass an integer or real actual
> argument corresponding to "scal", the compiler has to construct a descriptor
> at the call site. Finally, class(*) has aliasing implications that also add
> to the performance penalty.
>
> So if your main concern is efficiency, the generic interface blocks you had
> originally are the best.

You have convinced me: I hold on my original generic interface.

Thank you.

My best regards

James Van Buskirk

unread,
Oct 27, 2012, 1:27:31 PM10/27/12
to


"Stefano Zaghi" <stefan...@gmail.com> wrote in message
news:98b18872-8023-4afb...@googlegroups.com...
A virus has prevented me from participating in this thread until
now. It seem to me that for the INCLUDE method, which attempts
to mimic C++ templates, you only need 2 procedures written out:

C:\gfortran\clf\vec_template>type templates.i90
elemental function scalar_times_vec(Qscalar, vector)
type(vec) scalar_times_vec
type(vec), intent(in) :: vector
intent(in) :: Qscalar
type(vec) vec_times_scalar
entry vec_times_scalar(vector, Qscalar)
scalar_times_vec = vec( &
x = Qscalar*vector%x, &
y = Qscalar*vector%y, &
z = Qscalar*vector%z)
end function scalar_times_vec

C:\gfortran\clf\vec_template>type vec_template.f90
module mykinds
implicit none
integer, parameter :: R4P = selected_real_kind(6,30)
integer, parameter :: R8P = selected_real_kind(15,300)
integer, parameter :: I1P = selected_int_kind(2)
integer, parameter :: I2P = selected_int_kind(4)
integer, parameter :: I4P = selected_int_kind(9)
integer, parameter :: I8P = selected_int_kind(18)
end module mykinds

module vec_def
use mykinds
implicit none
private
type, public :: vec
real(R8P) x
real(R8P) y
real(R8P) z
end type vec
end module vec_def

module vec_template
use vec_def
implicit none
private
public operator(*)
interface operator(*)
module procedure cross
end interface operator(*)
contains
elemental function cross(x,y)
type(vec) cross
type(vec), intent(in) :: x
type(vec), intent(in) :: y

cross = vec( &
x = x%y*y%z-x%z*y%y, &
y = x%z*y%x-x%x*y%z, &
z = x%x*y%y-x%y*y%x)
end function cross
end module vec_template

module R4P_template
use mykinds
use vec_def
implicit real(R4P) (Q)
private
public operator(*)
interface operator(*)
module procedure scalar_times_vec, vec_times_scalar
end interface operator(*)
contains
include 'templates.i90'
end module R4P_template

module R8P_template
use mykinds
use vec_def
implicit real(R8P) (Q)
private
public operator(*)
interface operator(*)
module procedure scalar_times_vec, vec_times_scalar
end interface operator(*)
contains
include 'templates.i90'
end module R8P_template

module I1P_template
use mykinds
use vec_def
implicit integer(I1P) (Q)
private
public operator(*)
interface operator(*)
module procedure scalar_times_vec, vec_times_scalar
end interface operator(*)
contains
include 'templates.i90'
end module I1p_template

module I2P_template
use mykinds
use vec_def
implicit integer(I2P) (Q)
private
public operator(*)
interface operator(*)
module procedure scalar_times_vec, vec_times_scalar
end interface operator(*)
contains
include 'templates.i90'
end module I2p_template

module I4P_template
use mykinds
use vec_def
implicit integer(I4P) (Q)
private
public operator(*)
interface operator(*)
module procedure scalar_times_vec, vec_times_scalar
end interface operator(*)
contains
include 'templates.i90'
end module I4p_template

module I8P_template
use mykinds
use vec_def
implicit integer(I8P) (Q)
private
public operator(*)
interface operator(*)
module procedure scalar_times_vec, vec_times_scalar
end interface operator(*)
contains
include 'templates.i90'
end module I8p_template

module vec_mod
use vec_def
use vec_template
use R4P_template
use R8P_template
use I1P_template
use I2P_template
use I4P_template
use I8P_template
end module vec_mod

program test
use mykinds
use vec_mod
implicit none
type(vec) a, b
real(R4P) x4
real(R8P) x8
integer(I1P) i1
integer(I2P) i2
integer(I4P) i4
integer(I8P) i8

a = vec(1, 2, 3)
b = vec(2, 3, 4)
x4 = 2
x8 = 3
i1 = 4
i2 = 5
i4 = 6
i8 = 7

write(*,*) a*b
write(*,*) x8*b
write(*,*) x4*b
write(*,*) i8*b
write(*,*) i4*b
write(*,*) i2*b
write(*,*) i1*b
write(*,*) a*x8
write(*,*) a*x4
write(*,*) a*i8
write(*,*) a*i4
write(*,*) a*i2
write(*,*) a*i1
end program test

C:\gfortran\clf\vec_template>gfortran vec_template.f90 -ovec_template
vec_template.f90:132.12:

program test
1
Error: Name 'scalar_times_vec' at (1) is an ambiguous reference to
'scalar_times
_vec' from module 'r4p_template'
vec_template.f90:132.12:

program test
1
Internal Error at (1):
Unable to find symbol scalar_times_vec

I think the error above is in gfortran; my code looks OK.
Note that there are several refinements that have been
suggested by other posters to the INCLUDE method such as
using implicit typing to permit both integer and real types
to be used in the template code and ENTRY statements for
commutative operators, and not publishing the specific
names.

The implicit typing has limitations and could be avoided
if compilers implemented syntax like:

module m1
integer, parameter, private :: dp = kind(1.0d0)
type(real(dp)), parameter, private :: xdp = 0
end module m1

module m2
use m1, only: template_type => real(dp)
type(template_type) x
end module m2

but I don't know if the above is standard conforming and neither
ifort nor gfortran allow it. It's a pity that one can clone
procedures like:

procedure(any_old_procedure) template_procedure

but not types like:

variable(any_old_variable) template_variable

The former standard usage seems much more complicated than the latter
nonstandard one because not only does the compliler have to pass on
the return type of function any_old_procedure, but also the
characteristics of its arguments and the hidden procedure that
processes the specification-part of any_old_procedure so that
the calling program can know the shape and any length type
parameters of its result variable. Of course some may consider
specification statements such as:

variable(any_old_variable), parameter :: one = 1

to be confusing, but it's no worse than some other terminology in
the Fortran language definition.

--
write(*,*) transfer((/17.392111325966148d0,6.5794487871554595D-85, &
6.0134700243160014d-154/),(/'x'/)); end


Stefano Zaghi

unread,
Oct 30, 2012, 8:47:18 AM10/30/12
to
Hi James,
thank you for your suggestion. The use of ENTRY is interesting. Instead I do not like the "implicit typing". Nevertheless I am not sure I understand your last trick:

"""
module m1
integer, parameter, private :: dp = kind(1.0d0)
type(real(dp)), parameter, private :: xdp = 0
end module m1

module m2
use m1, only: template_type => real(dp)
type(template_type) x
end module m2
"""

Can you give me more details?

Thank you again.

James Van Buskirk

unread,
Oct 30, 2012, 10:37:57 PM10/30/12
to

"Stefano Zaghi" <stefan...@gmail.com> wrote in message
news:3df2fffc-a065-42aa...@googlegroups.com...
Module m1 should be self-explanatory. In f2008, you can use
intrinsic types in declaration statements like user-defined types.
Doing so makes the REAL type (hopefully with its kind type
parameter set to 8) a public entity of module m1.

The point of module m2 is that we want to have a name of our
choosing for this type so that we can create template code that
has this type name as the template type name. It works fine
for user-defined types or for intrinsic types that only differ
in their type parameters, but if you want to mix REAL and
INTEGER types, or any intrinsic type (except for C_PTR or
C_FUNPTR) with user-defined types, Fortran does not provide
any syntax to allow this, assuming my module m2 above is
invalid.

Just read any data structures textbook, such as Main & Savitch,
if you want to see the utility of this template style of coding.
It's frustrating that Fortran has this shortcoming; it could be
fixed by creating an intrinsic module with names for all the
intrinsic type/kind combinations although character data would
be left out because you couldn't give a name for each possible
value of their length type parameter. Another possibility
would be a VARIABLE statement that would work much like the
PROCEDURE statement does so that you don't need to attempt to
rename the ineffible name of an intrinsic type to declare
objects of an intrinsic or user-defined type with the same
syntax, as is required for template code. I suppose the
standards committee hasn't brought something like this forward
because the Fortran solution would have shortcomings compared
to the C++ one in that C++ uses text inclusion via a preprocessor
for its template mechanism so that it need not generate code
for template functions until they are needed. Fortran does things
differently with separate compilation and it would be difficult
to avoid compiling all possible procedures. Even though Fortran
templates wouldn't be perfect, at least they would avoid the
workaround of implicit typing which has limitations (how do you
write an interface body using type implicit in the module, or
think about the type definition of a linked list node where the
data member's type is only available via implicit typing.) But
implicit typing is good enough for the problem you posted, and
at least it's there in Fortran, so I would not hesitate to use
it (assuming it didn't ICE gfortran as my example did.)

Ian Harvey

unread,
Oct 31, 2012, 12:25:19 AM10/31/12
to
To confirm your assumption, that's not standard F2008. The syntax only
allows for the thing on the right of the => to be a name.
Me too - in terms of wanting generic programming. I've been reading
some of the proposals that were floating around at the start of f2008
development.

(I'm not so sure that modern C++ still allows for an implementation that
is just based on a text (or even token) substitution approach - I think
the compiler has to have some idea of what's going on when it parses the
template code (thinking about required diagnostics, etc). But I could
very well be wrong. Regardless the presence or otherwise of "short
comings" in a language comparison pissing contest isn't really grounds
for excluding a feature - that should just look at the cost/benefit of
the feature for the Fortran ecosystem in isolation.)

Given the existing syntax and module infrastructure that Fortran has,
adding language support for generic programming to Fortran seems
tantalisingly close.

If Fortran obtained some sort of template facility I'd hope that it
didn't go down the path where you need to specify all required
combinations of types, etc as part of defining the template, as that
defeats one of the advantages of generic programming - write code today
that is generically useful, but the specific application (specific
types, in a Fortran context specific kinds) won't be known until
tomorrow. Same comment applies to the need for the compiler to generate
all possible combinations when it first sees the template definition.

What you want instead is something more along the lines of "This
procedure can handle integers of unspecified kind (or some type(s), that
meets some specified requirements). Tomorrow I'll tell you specifically
what kind (or type) I need it to work for, but given what you know
today, does it make syntactic sense?"

You don't want the simple macro text-expansion approach. Compilers are
able to be smarter than that.

rob...@gmail.com

unread,
Nov 15, 2012, 9:55:38 AM11/15/12
to
On Tuesday, October 23, 2012 8:34:31 AM UTC+1, Stefano Zaghi wrote:
>
> interface operator (*)
> module procedure vec_mul_vec
> module procedure ScalR8P_mul_vec
> module procedure ScalR4P_mul_vec
> module procedure ScalI8P_mul_vec
> module procedure ScalI4P_mul_vec
> module procedure ScalI2P_mul_vec
> module procedure ScalI1P_mul_vec
> module procedure vec_mul_ScalR8P
> module procedure vec_mul_ScalR4P
> module procedure vec_mul_ScalI8P
> module procedure vec_mul_ScalI4P
> module procedure vec_mul_ScalI2P
> module procedure vec_mul_ScalI1P
>
> endinterface

I recently faced a similar problem and I've had excellent results with PyF95++.

https://sourceforge.net/projects/blockit/
http://sourceforge.net/apps/mediawiki/blockit/index.php?title=PyF95%2B%2B

It is a Fortran templating tool written in Python that has a number of convenient features for this sort of thing.

To give you an idea this is how I used it to template a Matlab interface over different numeric types and ranks:

https://github.com/robince/MatlabAPI_lite/blob/master/MatlabAPImx.F90T

Cheers

Robin
0 new messages