Home > Archive > Fortran > September 2005 > Passing functions CONTAINed in a subroutine to other functions
You are viewing an archived Text-only version of the thread.
To view this thread in it's original format and/or if you want to reply to
this thread please [click here]
| Author |
Passing functions CONTAINed in a subroutine to other functions
|
|
| bricknews@gmail.com 2005-09-16, 6:59 pm |
| Hi.
In a code I'm working on, numerical integration is frequently used. I
made an integration interface that requires the user to pass a function
of only the integration variable to it. The integrands are dependant on
some values that are loop-invarient over the integration points.
This is currently handled by CONTAINing the simplified function in a
larger function scope, eg:
function bigfun(foo, bar, baz)
...
bigfun = integrate_tet(smallfun)
....
contains
real smallfun(lambda)
real, dimension(4), intent(in) :: lambda
smallfun = (calculations involving foo, bar, baz)
end
end
Is this use of a contained function legal f90? It works fine with ifort
8.1, but it does not want to compile on an SGI machine. Using a module
to contain the larger scope seems to work on the SGI, but refactoring
all the code this way would be quite time consuming.
The SGI machine is running a pretty old version of MIPSpro (7.3.1.3m),
so if the above code is legal I might try to update the SGI's compiler.
Otherwise, I guess I should make the code conforming.
Advice?
Thanks
Neilen
| |
| Tim Prince 2005-09-16, 6:59 pm |
| bricknews@gmail.com wrote:
> Hi.
>
> In a code I'm working on, numerical integration is frequently used. I
> made an integration interface that requires the user to pass a function
> of only the integration variable to it. The integrands are dependant on
> some values that are loop-invarient over the integration points.
>
> This is currently handled by CONTAINing the simplified function in a
> larger function scope, eg:
>
> function bigfun(foo, bar, baz)
> ...
>
> bigfun = integrate_tet(smallfun)
>
> ...
>
> contains
>
> real smallfun(lambda)
> real, dimension(4), intent(in) :: lambda
>
> smallfun = (calculations involving foo, bar, baz)
>
> end
> end
>
> Is this use of a contained function legal f90? It works fine with ifort
> 8.1, but it does not want to compile on an SGI machine.
No doubt, you could find expert answers to this in the c.l.f archive.
This common extension is not "legal f90," unless integrate_tet() is also
contained in the same bigfun.
| |
| Arjen Markus 2005-09-16, 6:59 pm |
| According to the standard, you can not pass contained
functions/subroutines to
another function/subroutine like that, as Tim says - I was even unaware
of
compilers that do allow this.
The reason may or may not be good - depending on your point of view:
it breaks the "privateness" of these contained functions/subroutines
and
the privateness of the data of the containing program unit.
Regards,
Arjen
| |
| bricknews@gmail.com 2005-09-16, 6:59 pm |
| HI
Thanks to all who replied. I did indeed try searching the c.l.f.
archive, but perhaps my searching methodology is lacking.
Thanks for the info, now I know I have to change my code. Motivation is
much higher if you know you have no choice ;P
Cheers
Neilen
| |
| Michael Metcalf 2005-09-16, 6:59 pm |
|
<bricknews@gmail.com> wrote in message
news:1126879261.866961.82460@g47g2000cwa.googlegroups.com...
> HI
>
> Thanks to all who replied. I did indeed try searching the c.l.f.
> archive, but perhaps my searching methodology is lacking.
>
> Thanks for the info, now I know I have to change my code. Motivation is
> much higher if you know you have no choice ;P
>
For what it's worth, here is an outline based on the examples in Section
5.12 of "Fortran 95/2003 Explained".
Regards,
Mike Metcalf
module m
contains
real function minimum(a, b, func) ! Returns the minimum
! value of the function func(x) in the interval (a,b)
real, intent(in) :: a, b
interface
real function func(x)
real, intent(in) :: x
end function func
end interface
real :: f,x
:
f = func(x) ! invocation of the user function.
:
end function minimum
real function fun(x)
:
end function fun
end module m
program main
use m
real :: a, b, f
f = minimum(1.0, 2.0, fun)
:
end program main
| |
| Richard E Maine 2005-09-16, 6:59 pm |
| In article <1126877372.997793.308530@g44g2000cwa.googlegroups.com>,
"Arjen Markus" <arjen.markus@wldelft.nl> wrote:
> According to the standard, you can not pass contained
> functions/subroutines to another function/subroutine like that,
....
> The reason may or may not be good - depending on your point of view:
> it breaks the "privateness" of these contained functions/subroutines
> and the privateness of the data of the containing program unit.
The reason may or may not be good... but that isn't it.
That's not the reason that has been cited when rejecting this proposal.
There's even a note somewhere in the standard which suggests how an
extension that allows this should work. That note gives the reason.
Let's see, where is the note?....A grep for "instance" will probably
help me find it.... Ah. There. In f2003, note 12.16 in 12.4 (page 267).
"This standard does not allow internal procedures to be used as actual
arguments, in part to simplify the problem of ensuring that internal
procedures with recursive hosts access entities from the correct instance
(\ref{D12:Instances of a subprogram}) of the host. If, as an extension,
a processor allows internal procedures to be used as actual arguments,
the correct instance in this case is the instance in which the procedure
is supplied as an actual argument, even if the corresponding dummy
argument is eventually invoked from a different instance."
No, I am not going to argue now about whether this is a good reason.
Likewise, I am not going to debate about whether there would have been
other, better ways to address the problem or whether the restriction
could have been made narrower.
All I'm doing is pointing out the reason actually cited in the standard.
It is slightly unusual for the standard to cite a reason, partly because
it can be hard to get agreement on what the reason for something is.
When we have one of the rare cases where a reason is explicitly cited,
we might as well take advantage.
Oh, and if you don't want to wade through the standard-speak and
technical issues, my (very) short translation of the reason is
"implementation complications."
--
Richard Maine | Good judgment comes from experience;
email: my first.last at org.domain | experience comes from bad judgment.
org: nasa, domain: gov | -- Mark Twain
| |
| Arjen Markus 2005-09-19, 3:56 am |
| Oh, ah, hm, okay - I must admit I did not check the standard for this.
It just seemed a good reason/motivation for this restriction.
Regards,
Arjen
| |
| glen herrmannsfeldt 2005-09-19, 3:56 am |
| Richard E Maine wrote:
(someone wrote)
(snip)
[color=darkred]
> "This standard does not allow internal procedures to be used as actual
> arguments, in part to simplify the problem of ensuring that internal
> procedures with recursive hosts access entities from the correct instance
> (\ref{D12:Instances of a subprogram}) of the host. If, as an extension,
> a processor allows internal procedures to be used as actual arguments,
> the correct instance in this case is the instance in which the procedure
> is supplied as an actual argument, even if the corresponding dummy
> argument is eventually invoked from a different instance."
For comparison purposes only...
That sounds pretty much like what PL/I does, either with ENTRY
arguments, or ENTRY variables (like C function pointers).
http://publibz.boulder.ibm.com/cgi-.../ibm3lr30/6.4.6
As far as I know, C function pointers are usually simply addresses
and no instance is associated with them. Then again, C doesn't have
internal procedures.
C's setjmp() and longjmp(), though, I believe do include instance
information, as does PL/I LABEL variables and non-local GOTO statements.
-- glen
|
|
|
|
|