Intel® Fortran Compiler
Build applications that can scale for the future with optimized code designed for Intel® Xeon® and compatible processors.
28543 Discussions

All references to a RESULT keyword are recursive calls?

Espen_M_
Beginner
311 Views

The Intel(R) Fortran Compiler XE 13.0 User and Reference Guides states the following about the RESULT keyword:

However, if you use the RESULT keyword in a FUNCTION statement, you can specify a local variable name for the function result. In this case, all references to the function name are recursive calls, and the function name must not appear in specification statements.

My impression is that RECURSIVE routines are slower than non-RECURSIVE routines due to how variables may be allocated (the reason this was not allowed in F77). If my impression is correct, does that imply that whenever the RESULT keyword is used, there is an performance penalty? I use the RESULT keyword all the time as an alias for the function name, so that I can have descriptive function names (which tend to be relatively long) without having to use that name in the function body. Is this then a bad idea if performance is important?

0 Kudos
7 Replies
mecej4
Honored Contributor III
311 Views
Keywords cannot be referenced -- where such a reference may appear to exist, the keyword will be interpreted as a variable, possibly local and implicitly typed. I think that you misinterpret the documentation and that your statement about recursion causing slower running is an over-generalization. To address the first point only, consider this example: The first version, without the RESULT clause: [fortran]program xrec implicit none integer :: n,fac n=5 fac=factorial(n) write(*,*)n,fac stop contains function factorial(n) implicit none integer :: n, factorial factorial=1 if(n.le.1)return do while(n.gt.1) factorial=factorial*n write(*,*)n,factorial n=n-1 end do return end function factorial end program xrec [/fortran] In the internal function the function name is used in almost the same ways as a local variable. No recursion occurs, as the lines of output will show.

Next, the same program, slightly modified to use a RESULT clause: [fortran] program xrec1 implicit none integer :: n,fac n=5 fac=factorial(n) write(*,*)n,fac stop contains function factorial(n) result (fact) implicit none integer :: n, fact fact=1 if(n.le.1)return do while(n.gt.1) fact=fact*n write(*,*)n,fact n=n-1 end do return end function factorial end program xrec1 [/fortran] Again, note that no recursion occurs.

0 Kudos
Espen_M_
Beginner
311 Views
mecej4: The way you use fact as en alias for the function name (and output variable) factorial is exactly how I use it. I think maybe you misinterpreted my question though, or maybe I wasn't so clear to what in the quote I was refering to. The part that I wonder about is this: [...] all references to the function name are recursive calls, [...] As I interpret this the compiler creates the same code *as if* the RECURSIVE attrubute were also present. In your examples there aren't any actual recursive calls (only iterations), and, hence, there is no need for the compiler to 'take special care' of how the local variables are stored etc. In the following code there is actual recursion going on: [fortran] RECURSIVE FUNCTION factorial(n) RESULT(fact) INTEGER, INTETNT(IN) :: n INTEGER :: fact IF (n .GT. 1) THEN fact = n*factorial(n-1) ELSE fact = 1 END FUNCTION factorial [/fortran] Don't shoot me if the code is flawed, it's just for illustrating actual recursion. The point is: is the compiler creating machine code as if the function was actually recursive? And perhaps a follow-up: Even if the RECURSIVE attribute was present in a procedure that do not make any calls to other procedures (and hence cannot be recursive), will the compiler create code as if it actually were recursive?
0 Kudos
mecej4
Honored Contributor III
311 Views
is the compiler creating machine code as if the function was actually recursive?
I'd expect it to, unless the optimizer is invoked and is smart enough to replace the simpler recursive code with a non-recursive version with the same functionality. Here is the assembler output from your function: PUBLIC _FACTORIAL _FACTORIAL PROC NEAR ... call _FACTORIAL ... _FACTORIAL ENDP
Even if the RECURSIVE attribute was present in a procedure that do not make any calls to other procedures (and hence cannot be recursive), will the compiler create code as if it actually were recursive?
That would be up to the optimizer to decide. The Fortran standard does not specify such implementation details. The standard does specify in 12.6.5.2.1, w.r.t. the opposite question:
The RECURSIVE pre fix-spec shall appear if any procedure de fined by the subprogram directly or indirectly invokes itself or any other procedure de fined by the subprogram.
0 Kudos
Steven_L_Intel1
Employee
311 Views
The primary code effect of RECURSIVE is to allocate any local variables and data structures on the stack rather than statically. This is required if the procedure can be reentered while it is still active, whether due to an actual recursive call or a call from a thread context. (If OpenMP is enabled, stack storage is used by default.) This is not really any slower than static storage, but programs that mistakenly assume static storage may give wrong answers.
0 Kudos
Espen_M_
Beginner
311 Views
Oops, the example in my last code probably mislead this discussion off track from the original question. I'll repose it: Given a (non-recursive) function using a RESULT keyword, but without the RECURSIVE attribute. Will the machine code for this function differ from that of the same function programmed without using a RESULT keyword?
0 Kudos
Steven_L_Intel1
Employee
311 Views
No. Using RESULT allows you to reference the function and its return value separately. Otherwise, no difference.
0 Kudos
mecej4
Honored Contributor III
311 Views
Espen M. wrote:

Given a (non-recursive) function using a RESULT keyword, but without the RECURSIVE attribute. Will the machine code for this function differ from that of the same function programmed without using a RESULT keyword?

The short answer is "No". In fact, if you compile the two versions of the non-recursive function FACTORIAL above with the /Od /Fa options, you will find the assembler outputs to be identical. If you compile with debugging enabled, however, the symbol tables may differ slightly.
0 Kudos
Reply