- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
I assume that if I have any LOCAL variables within the routine, there will ab a separate copy of all of those
for each recursive call.
What if I have variables that I want to share between ALL recursive calls?
Would I use the SAVE attribute?
Maybe there is an article elaborating this topic. So far, I have not found it.
example:
recursive subroutine sub1
integer,SAVE::kcall
data kcall/0/
if(kcall < 20)call sub1
kcall=kcall+1
end subroutine
In the above example, I want to limit the recursions to 20 deep or less
Obviously, kcall has to be initialized some way.
And there has to be only one copy of it.
Maybe there is a BETTER way to do that?
Link Copied
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
The problem with using SAVE for this purpose (DATA implies SAVE, by the way), is that the initialization to 0 happens only on the first call. If you make another set of nested calls, the value of kcall will be retained and it will stop immediately. A better way is to have kcall as a dummy argument, passed as 0 on the initial call. The routine then tests kcall and if it wants to continue, calls itself again passing kcall+1.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
But what happens if you add a second call to sub1 from the main program? This is what I was getting at.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Or
Assume you use OpenMP, you would expect (require) each thread to achieve the same recursion level. Also, kcall=kcall+1 would not be thread safe in the event you actually want all threads to share an application-wide recursion level.
Using the passed in dummy argument is the way to go
** provided you do not
kcall=kcall+1
instead use:
call sub1(kcall+1, ...)
This will create a temporary on the stack for the call.
Jim Dempsey
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
I still am wondering if there is a way to share the same set of variables between ALL calls of the routine.
I have an application that requires that -
I could put those in a MODULE, of course, but maybe that isn't the best way to do it.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
It depends on what you want. If you want the variables used only by that routine, you can make them local and SAVE (and VOLATILE, I would recommend.) If the variables are used by a collection of routines, put the routines in a module and declare the variables in the module scope, marking them PRIVATE. If they are to be shared by the whole program, like COMMON, put them in a module.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
OK, I will experiment.
Thanks for your input ! !
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Steve Lionel (Intel) wrote:
It depends on what you want. If you want the variables used only by that routine, you can make them local and SAVE (and VOLATILE, I would recommend.) If the variables are used by a collection of routines, put the routines in a module and declare the variables in the module scope, marking them PRIVATE. If they are to be shared by the whole program, like COMMON, put them in a module.
Depending on the needs, derived types with type-bound procedures may be a worthwhile option for you to consider. It has the advantage of not requiring global and static (or volatile) variables which can help with parallel processing at the higher levels.
MODULE m !.. IMPLICIT NONE !.. PRIVATE TYPE, PUBLIC :: t CHARACTER(LEN=:), ALLOCATABLE :: MyName INTEGER :: n CONTAINS PROCEDURE, PASS(This), PUBLIC :: foo END TYPE t CONTAINS RECURSIVE SUBROUTINE foo(This, x) !.. Argument list CLASS(t), INTENT(IN) :: This INTEGER, INTENT(INOUT) :: x !.. IF (x < This%n) THEN x = x + 1 PRINT *, This%MyName, ': x = ', x CALL This%foo(x) END IF !.. RETURN END SUBROUTINE foo END MODULE m PROGRAM p USE m, ONLY : t !.. Local variables TYPE(t) :: A INTEGER :: x PRINT *, " Test #71: Recursion " A%MyName = "Thing One" A%n = 5 x = 0 CALL A%foo(x) STOP END PROGRAM p
When above code is executed,
Test #71: Recursion Thing One: x = 1 Thing One: x = 2 Thing One: x = 3 Thing One: x = 4 Thing One: x = 5 Press any key to continue . . .

- Subscribe to RSS Feed
- Mark Topic as New
- Mark Topic as Read
- Float this Topic for Current User
- Bookmark
- Subscribe
- Printer Friendly Page