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

Can a Fortran Function return both a value and an error status code?

284 views
Skip to first unread message

sgih...@gmail.com

unread,
Dec 5, 2016, 5:48:08 PM12/5/16
to
Does Fortran 2008 Functions support the option of returning both a value and some type of error status code? If not, how would you handle a situation like this?

Thanks....

Ian Harvey

unread,
Dec 5, 2016, 6:09:25 PM12/5/16
to
Yes, but...


Functions can modify their arguments.

FUNCTION f1(in, status)
INTEGER, INTENT(IN) :: in
INTEGER, INTENT(OUT) :: status
INTEGER :: f1
...

! Function result must be defined even if the
! function "fails".
f1 = ...
status = ...
END FUNCTION f1

...
INTEGER :: x, status
x = f1(1, status)
IF (status /= 0) ERROR STOP 'All gone bad!'

There are downsides to this approach (e.g. the function cannot be PURE,
language prohibitions on changes to entities that appear elsewhere
within the statement can be unintentionally violated) such that this is
discouraged by some Fortran style guidelines, including the style
guideline that I follow personally.


Functions can return derived types.

TYPE result_type
INTEGER :: value
INTEGER :: status
END TYPE result_type

FUNCTION f2(in)
INTEGER, INTENT(IN) :: in
TYPE(result_type) :: f2
...

! Because it is a function result, the object
! of derived type must be completely defined.
f2%value = ...
f2%status = ...
END FUNCTION f2

...
TYPE(result_type) :: y
y = f2(1)
IF (y%status /= 0) ERROR STOP 'I broke it :('


From a style perspective, it may be better to consider whether your
function should be a subroutine.

SUBROUTINE s3(in, value, status)
INTEGER, INTENT(IN) :: in
INTEGER, INTENT(OUT) :: value
INTEGER, INTENT(OUT) :: status

...
! If the subroutine fails, it may leave `value` undefined.
status = ...
END SUBROUTINE s3

...
INTEGER :: z, status
CALL s3(1, z, status)
IF (status /= 0) ERROR STOP 'Oh no, not again.'

Dick Hendrickson

unread,
Dec 5, 2016, 8:58:42 PM12/5/16
to
On 12/5/16 4:48 PM, sgih...@gmail.com wrote:
> Does Fortran 2008 Functions support the option of returning both a value and some type of error status code? If not, how would you handle a situation like this?
>
> Thanks....
>
Why would you want to return a status? Functions are meant to be used
in expressions; things like one = my_sin(x)**2 + my_cos(x)**2. ;) What
would you like to happen if my_sin returned a bad status?

If you're doing something like
value = function(x)
if (hidden_status ...

where there is no "real" expression

the solution is
call subroutine(x, value, status)
if (status ...

As Ian hinted at, Fortran allows a ton of optimization and an expression
like
IT (z*F(x,status) .eq. 0.0 .OR. F(x,status)*F(x,status).eq. 0.0) ...
might evaluate F 0, 1, 2, or 3 times and in any order.

Dick Hendrickson

Gary Scott

unread,
Dec 5, 2016, 10:25:47 PM12/5/16
to
On 12/5/2016 7:58 PM, Dick Hendrickson wrote:
> On 12/5/16 4:48 PM, sgih...@gmail.com wrote:
>> Does Fortran 2008 Functions support the option of returning both a
>> value and some type of error status code? If not, how would you handle
>> a situation like this?
>>
>> Thanks....
>>
> Why would you want to return a status? Functions are meant to be used
> in expressions; things like one = my_sin(x)**2 + my_cos(x)**2. ;) What
> would you like to happen if my_sin returned a bad status?

i know you know...but most windows API functions have a return status
code as the function return value...results are very often returned via
function arguments...making this sort of mathematical purist argument
just isn't going to go anywhere in the real world.

Clive Page

unread,
Dec 6, 2016, 5:16:05 AM12/6/16
to
On 06/12/2016 01:58, Dick Hendrickson wrote:
> Why would you want to return a status? Functions are meant to be used
> in expressions; things like one = my_sin(x)**2 + my_cos(x)**2. ;) What
> would you like to happen if my_sin returned a bad status?

Well, suppose the function itself called some function like sqrt(x)
where x had the possibility of being negative. Assuming we are talking
about real rather than complex arithmetic, that will produce a "bad"
status. What to do in the user-written function? First you have to
test for negative x and respond in some way rather than call the SQRT.
One possibility is for the function to return some sort of flag value,
such as +Inf, -Inf, or NaN. To some extent these will propagate
sensibly through real expressions, so that you only need to test for a
flag value at the end. This isn't an entirely satisfactory solution,
but may work in some cases.


--
Clive Page

Gordon Sande

unread,
Dec 6, 2016, 10:35:25 AM12/6/16
to
When a function returns a status code and is invoked in an IF statement
the reasonable view is that it is a local idiom for CALL.

A CALL with a following status check takes two lines but the IF status check
on a function only takes one line. I have seen code that used this. At first
it looked strange but when there are twenty or thirty such calls on a single
page it suddenly looked quite normal.




Ron Shepard

unread,
Dec 6, 2016, 11:53:48 AM12/6/16
to
On 12/6/16 9:35 AM, Gordon Sande wrote:
>>> As Ian hinted at, Fortran allows a ton of optimization and an expression
>>> like
>>> IT (z*F(x,status) .eq. 0.0 .OR. F(x,status)*F(x,status).eq. 0.0) ...
>>> might evaluate F 0, 1, 2, or 3 times and in any order.
>>>
>>> Dick Hendrickson
>
> When a function returns a status code and is invoked in an IF statement
> the reasonable view is that it is a local idiom for CALL.

Just to avoid confusion, that is NOT what is happening in the above
statement. In the above, the return status is returned through the
argument, and the computed value is returned through the function value.

In your example, the computed value, or values if there are more than
one, are returned through the function arguments and the return status
is returned through the function value.

> A CALL with a following status check takes two lines but the IF status
> check
> on a function only takes one line. I have seen code that used this. At
> first
> it looked strange but when there are twenty or thirty such calls on a
> single
> page it suddenly looked quite normal.

It is just as easy, and almost the same number of characters, to put the
call and the if() test on the same line, separated with a semicolon. If
you are programming with an API that uses functions in this way, then
you have little choice, but if you are controlling the API, then you can
choose to do it either way.

$.02 -Ron Shepard

Dick Hendrickson

unread,
Dec 6, 2016, 12:56:25 PM12/6/16
to
On 12/5/16 9:25 PM, Gary Scott wrote:
> On 12/5/2016 7:58 PM, Dick Hendrickson wrote:
>> On 12/5/16 4:48 PM, sgih...@gmail.com wrote:
>>> Does Fortran 2008 Functions support the option of returning both a
>>> value and some type of error status code? If not, how would you handle
>>> a situation like this?
>>>
>>> Thanks....
>>>
>> Why would you want to return a status? Functions are meant to be used
>> in expressions; things like one = my_sin(x)**2 + my_cos(x)**2. ;) What
>> would you like to happen if my_sin returned a bad status?
>
> i know you know...but most windows API functions have a return status
> code as the function return value...results are very often returned via
> function arguments...making this sort of mathematical purist argument
> just isn't going to go anywhere in the real world.
>
Yes, true. But, Fortran tries to have general purpose universal rules
(usually). Doing some sort of special case rule for functions used only
in IF statements or as the single term in the right hand side of an
assignment is a problem.

There's nothing terribly wrong with returning values via the argument
list and a status as the function value. It's just not a good general
solution. If someone else later on modifies
IF ( Some_API (list1) ) whatever
into
IF ( Some_API (list1) .or. Other_API (list2)) whatever
list1 and/or list2 might or might not be modified in any order.

khb

unread,
Dec 6, 2016, 1:27:23 PM12/6/16
to
...many sage remarks elided...

Environments based on C have, of course, a C model of behavior... where functions and subroutines are "indistinguishable" and everything has a return code (and many things have a global (COMMON-like) ERRNO in addition!).

It doesn't mean one should pollute the rest of one's code to look like C ;>

Marco

unread,
Dec 7, 2016, 3:39:59 AM12/7/16
to
I think if you want to rely on error propagations in an expression you
should use a derived type as noted above with (value,err_flag) and
overload also **, +, ... In fact, it is good that you are forced to
overload these operators, since then you are sure to be in control of
your error handling.

Marco

Myron A. Calhoun

unread,
Dec 7, 2016, 10:10:09 AM12/7/16
to
>> MUCH skipped
>It is just as easy, and almost the same number of characters, to put the
>call and the if() test on the same line, separated with a semicolon....

That assumes, of course, that your Fortran compiler allows semicolons.
G77 (which I use) apparently doesn't.
--
-- Myron A. Calhoun.
Five boxes preserve our freedoms: soap, ballot, witness, jury, and cartridge
Most gun control is like trying to reduce drunk driving
by making it tougher for sober people to own cars.

dpb

unread,
Dec 7, 2016, 10:47:27 AM12/7/16
to
On 12/07/2016 9:03 AM, Myron A. Calhoun wrote:
>>> MUCH skipped
>> It is just as easy, and almost the same number of characters, to put the
>> call and the if() test on the same line, separated with a semicolon....
>
> That assumes, of course, that your Fortran compiler allows semicolons.
> G77 (which I use) apparently doesn't.

Statement separator semicolon was introduced with F90.
0 new messages