Passing array valued functions as argument to function.
Author Message
Passing array valued functions as argument to function.

Hi all,

I've spent several years working with fortran 95, yet somehow I've
never needed to write functions which use other functions as arguments
until today. I've struggled to make sense of this from the books I
have to hand (no M&R just now).

The purpose of the code will be to compute a definite integral of the
passed function. Here's a toy code example of what I naively expected
to work:

MODULE one
CONTAINS
FUNCTION f1(x_in) RESULT (y_out)
DOUBLE PRECISION :: x_in(:)
DOUBLE PRECISION :: y_out(SIZE(x_in))
y_out = 2*x_in
END FUNCTION f1
END MODULE one

PROGRAM test
USE one
DOUBLE PRECISION :: a(3)=(/ 1.0d0,2.0d0,3.0d0 /)
PRINT*, f1(a)
PRINT*, eval(a,f1)

CONTAINS
FUNCTION eval(x_in,func) RESULT (y_out)
DOUBLE PRECISION :: x_in(:)
DOUBLE PRECISION :: y_out(SIZE(x_in))
DOUBLE PRECISION, EXTERNAL :: func

y_out = func(x_in)
END FUNCTION eval
END PROGRAM test

but I get:

bash\$ f95 test.f90 #(Note f95=Nag's compiler on linux.)
Error: test.f90, line 14: Array supplied for scalar argument FUNC (no.
2) of EVAL
[f95 error termination]

Could someone explain how this is meant to be done in Fortran 95.
Many thanks,
Yours,
andy.

PS:
I'd also much appreciate an explanation of why when I replace the
function f1 with

FUNCTION f1(x_in) RESULT (y_out)
DOUBLE PRECISION :: x_in(:)
DOUBLE PRECISION :: y_out
y_out = 2*x_in(1)
END FUNCTION f1

Tue, 08 May 2007 21:51:53 GMT
Passing array valued functions as argument to function.
CVF 6.6C says:
Error: The shape matching rules of actual arguments and
dummy arguments have been violated.   [F1]
PRINT*, eval(a,f1)
-----------------^

which is because you declare the second argument of eval to be

Quote:
>     DOUBLE PRECISION, EXTERNAL :: func

while f1 returns a rank-one double-precision array. If, instead, you
replace this line by

INTERFACE
FUNCTION func(x_in) RESULT (y_out)
DOUBLE PRECISION :: x_in(:)
DOUBLE PRECISION :: y_out(SIZE(x_in))
END FUNCTION func
END INTERFACE

at least CVF compiles the code and produces the correct result:

2.00000000000000        4.00000000000000        6.00000000000000
2.00000000000000        4.00000000000000        6.00000000000000

Jan

Tue, 08 May 2007 22:07:46 GMT
Passing array valued functions as argument to function.
| Hi all,
|
| I've spent several years working with Fortran 95, yet somehow I've
| never needed to write functions which use other functions as arguments
| until today. I've struggled to make sense of this from the books I
| have to hand (no M&R just now).
|
| The purpose of the code will be to compute a definite integral of the
| passed function. Here's a toy code example of what I naively expected
| to work:
|
| MODULE one
| CONTAINS
|   FUNCTION f1(x_in) RESULT (y_out)
|     DOUBLE PRECISION :: x_in(:)
|     DOUBLE PRECISION :: y_out(SIZE(x_in))
|     y_out = 2*x_in
|   END FUNCTION f1
| END MODULE one
|
| PROGRAM test
|   USE one
|   DOUBLE PRECISION :: a(3)=(/ 1.0d0,2.0d0,3.0d0 /)
|   PRINT*, f1(a)
|   PRINT*, eval(a,f1)
|
| CONTAINS
|   FUNCTION eval(x_in,func) RESULT (y_out)
|     DOUBLE PRECISION :: x_in(:)
|     DOUBLE PRECISION :: y_out(SIZE(x_in))
|     DOUBLE PRECISION, EXTERNAL :: func
|
|     y_out = func(x_in)
|   END FUNCTION eval
| END PROGRAM test
|
| but I get:
|
| bash\$ f95 test.f90 #(Note f95=Nag's compiler on linux.)
| Error: test.f90, line 14: Array supplied for scalar argument FUNC (no.
| 2) of EVAL
| [f95 error termination]
|
| Could someone explain how this is meant to be done in Fortran 95.

That was a nice (almost good) try. However, as you probably know:

- functions returning arrays require an explicit interface
- funcions with assumed-shape dummies require an explicit interface.

Your f1 above fulfills both conditions.

You don't have an explicit interface there -- only DOUBLE PRECISION,
EXTERNAL, which is not good enough. Even if you did USE one, and
"Eval" is internal to the program, "Eval" still does not know that
its dummy argument "Func" is associated with "F1". Compilers are
not required to look that deep into your thoughts.

Since func is a dummy argument, the only means to achieve the explicit
interface is the INTERFACE block. Instead of

DOUBLE PRECISION, EXTERNAL :: func

use
INTERFACE
FUNCTION func(x_in) RESULT(y_out)
DOUBLE PRECISION :: x_in(:)
DOUBLE PRECISION :: y_out(SIZE(x_in))
END FUNCTION
END INTERFACE

and there you are.

The second sigsegv is again consequence of lack of explicit interface --
without it, "Eval" "presumes" it has assumed-size rather than
assumed-shape dummy argument, and that mismatch causes the sigsegv.

--
Jugoslav
___________
www.geocities.com/jdujic

Tue, 08 May 2007 22:33:25 GMT
Passing array valued functions as argument to function.
[snip]

Quote:
> You don't have an explicit interface there -- only DOUBLE PRECISION,
> EXTERNAL, which is not good enough. Even if you did USE one, and
> "Eval" is internal to the program, "Eval" still does not know that
> its dummy argument "Func" is associated with "F1". Compilers are
> not required to look that deep into your thoughts.

Dear Jan and Jugoslav,

Thanks for your replies, they solved my problem. There's a lot more
Fortran 95 left for me to learn, and I will read up on INTERFACE
blocks!

Thanks,
andy

Fri, 11 May 2007 18:22:24 GMT
Passing array valued functions as argument to function.

Quote:
> Thanks for your replies, they solved my problem. There's a lot more
> Fortran 95 left for me to learn, and I will read up on INTERFACE blocks!

I believe the example we gave you is the 1 in the 1.5 reasons to actually
use INTERFACE blocks. The other 0.5 is when interfacing with library code
you do not control, and for which no module file are available. All other
documented uses should not be used, because better alternatives are available.
So you might as well read up other things, but not the{*filter*}details of
INTERFACE blocks.

Jan

Fri, 11 May 2007 18:33:47 GMT
Passing array valued functions as argument to function.

Quote:

> I believe the example we gave you is the 1 in the 1.5 reasons to actually
> use INTERFACE blocks....
> So you might as well read up other things, but not the{*filter*}details of
> INTERFACE blocks.

Yes. Some textbooks have been known to introduce interface bodies
too early, with the result that people try to overuse them (in
my opinion).  I really recommend that you *NOT* use them much;
you just happen to have found one of the few places where you
do need them.  Some people end up trying to use them in places
where they not only aren't needed, but aren't even allowed.

I'd agree with Jan's 1.5 reasons, but to me this is the 1/2.  Almost
all of my interface bodies are for external library routines,
particularly C ones.  So I'd label that as the 1 and dummy procedures
as the 1/2, but we are close enough.

--
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

Sat, 12 May 2007 02:34:08 GMT
Passing array valued functions as argument to function.

Quote:
> I'd agree with Jan's 1.5 reasons, but to me this is the 1/2.  Almost
> all of my interface bodies are for external library routines,
> particularly C ones.  So I'd label that as the 1 and dummy procedures
> as the 1/2, but we are close enough.

Hmmm - I put the dummy procedures as counting fully because in this case
there is a requirement to use them in scenarios as posited by the OP.
The case of the external libraries count, IMO, as the 0.5 because they
are a nice-to-have, additional-safety-net, and-so-on, feature, but not a
requirement to get compileable code.

Jan

Sat, 12 May 2007 16:15:34 GMT

 Page 1 of 1 [ 7 post ]

Relevant Pages