1-12 RECURSION
***************
(Thanks to Dieter Britz for the excellent comments, and to Craig Burley
for the corrections)
A small glossary
----------------
ACTIVATION RECORD Context associated with a given execution of a procedure
CONTEXT The state (values) of all variables at a given time
ENTRY POINT The place in the code where a routine starts executing
INSTANCE Another word for procedure activation
INVOCATION Calling a procedure
STACK A dynamic data structure (see below)
STACK POINTER A variable keeping the place of the stack's top
STATIC MEMORY Pre-allocated by the compiler (at compile time)
Introduction
------------
Recursion is calling a procedure from itself, directly (simple recursion)
or via calls to other procedures (mutual recursion). FORTRAN 77 does not
allow recursion, Fortran 90 does, (recursive routines must be explicitly
declared so).
Most FORTRAN 77 compilers allow recursion, some (e.g. DEC) require
using a compiler option (see compiler options chapter). The GNU g77,
which conforms strictly to the Fortran 77 standard, doesn't allow
recursion at all.
Recursion is usually less computationally efficient, compiler generated
procedure calls introduce overhead when storing all variables before a
procedure call and loading them back upon entering the procedure.
Automatic optimizations reduce the overhead associated with procedure
calls by eliminating redundant store/load operations to some degree,
but of course hand optimizing may improve upon that.
Efficiency is usually not the most important consideration when
choosing an algorithm, in the name of good programming we already
agreed to gladly suffer some measure of inefficiency.
In spite of the inherent inefficacy, recursion is important as the
natural solution to some problems is a recursive algorithm,
for example:
1) Identifying pixels belonging to the same 'blob'
2) Searching a tree-structured database
Writing a program using a recursive algorithm is usually difficult,
every small mistake, and in a recursive procedure, almost every
modification is a mistake, renders the procedure useless.
If your compiler doesn't support recursion, or you want to write a
fully portable program, or you want your program to be more efficient,
you can implement a recursive algorithm by manual simulation.
Simultaneous invocations of a procedure
---------------------------------------
Why the execution of recursive procedures requires special treatment?
Non-recursive programs have the property that at any given time many
procedures may be 'active', but only one 'instance' of a given procedure
is 'active'.
That means that non-recursive programs can be implemented STATICALLY,
i.e. each of the various variables (and arrays) used in the program are
assigned a pre-determined location in main memory at compile time
(subject to relocation by the link editor).
The characteristic property of recursion is that different invocation
of the same procedure are active at the same time, and the variables
associated with each invocation must be kept separately, so they may
hold different values.
We need to keep more than one copy of the procedure set of variables
(the code may be shared), one for each possible activation. Clearly
the simple static memory allocation scheme fails for recursive procedures,
and something more elaborate is needed.
Simple-minded implementation of recursion
-----------------------------------------
Let's say we want to implement a procedure that call itself, and
for some reason or other we know that the 'call depth' is less than
say 100 activations.
We create 100 copies of the procedure, name them in some way to keep
the names unique, e.g. SUB001, SUB002, ... ,SUB100, the CALL statements
inside each copy will refer to the next one, i.e. SUB001 will call
SUB002, SUB002 will call SUB003, ... and instead of the CALL statement
in SUB100 we will put a STOP 'Not enough copies '.
In this way we can perform recursion with a compiler that supports
only a static memory allocation scheme. Of course this method is very
inefficient and wasteful, We don't need to duplicate the procedure's
code, only the data part (activation record).
The solution to the problem of managing several 'activation records'
at the same time is the STACK data structure.
The stack data structure
------------------------
A stack is a sequence of memory locations with an associated STACK POINTER
that points to the 'current location', a stack can be manipulated by two
operations: PUSH and POP.
Stacks (like main-memory) are really one-dimensional entities, they go
from location 0 to location N, N is supposed to be large enough for the
task on hand ('real' stacks may go from -N to 0).
All locations 'below' the current value of the stack pointer are
considered to contain valid values, all locations above are considered
'garbage' left from previous operations. The stack can 'grow' into
the garbage area if needed.
PUSH increments the stack pointer, and puts a value at the location
the stack pointer points to, so it will point to the next available
place on the stack.
POP takes the value pointed to by the stack pointer, and decrements
the stack pointer, thus 'trashing' that location.
0006 |013|
0005 |140| GARBAGE AREA
0004 |112|
0003 |358|<----Stack-pointer
0002 |871|
0001 |348| VALID DATA AREA
0000 |231|
+---+
Address Data
Placing activation records on the stack
---------------------------------------
An ACTIVATION RECORD is a memory region holding the variables associated
with a certain activation (instance) of a procedure, and some control
information. Activation records are placed on the stack in the order
of activation.
Recursion simulation
--------------------
You can simulate recursion in FORTRAN 77, in an efficient way. The
warnings about the sensitivity of recursive procedures to programming
errors, apply even more to simulated recursion.
The general idea behind recursion simulation is to replace the recursion
with some suitable DO loop.
The straightforward method to simulate recursion is to closely imitate
the way compilers implement recursive procedure calls, that way we will
get a bulky and inefficient code, that can be manually optimized.
With enough experience you can do it more informally, replace the call
to the recursive procedure with a GOTO and add the necessary data
structures as needed.
Remember that the recursive algorithm may be equivalent to a simple
iterative algorithm, and imitating a compiler may hide that simple
algorithm behind redundant complexity.
Implementation of recursion simulation: general scheme
------------------------------------------------------
This is a general scheme for simulating one procedure calling
itself (simple recursion). See the following text for explanation
of the scheme.
Data-declarations (Of Modified data structures)
.......................................
stack-pointer = 1
Initialize the stack (First activation)
Entry-point:
Read local variables from the stack
.......................................
.-----------------------------------------.
| A recursive call: |
| stack-pointer = stack-pointer + 1 |
| Store local variables on the stack |
| GOTO Entry-point |
'-----------------------------------------'
.......................................
stack-pointer = stack-pointer - 1
IF (stack-pointer .GE. 1) GOTO Entry-point (exit point!)
Implementation of recursion simulation: data structures
-------------------------------------------------------
We need to keep the value of each variable for each activation of the
procedure, so it's clear we should replace every scalar variable with
a 1D array of the same data type (REAL etc.), and size large enough
to hold all expected activations. The array will be indexed by the
'call depth', the first activation will have index 1, the second and
third will be 2,3...
Similarly we will replace a 1D array by a 2D array, a 2D array by a
3D array, etc:
REAL scalar, array(10)
Will be replaced by:
INTEGER MAXACT
PARAMETER(MAXACT = 200)
REAL scalar, Xscalar(MAXACT), array(10), Xarray(10, MAXACT)
We add the expanded variables to the original ones, the original
variables will serve as 'local' variables (we will implement a
call by value parameter passing mechanism), the expended variables
taken together will serve as our simulated stack.
The added dimension is put last, it's more efficient that way because
of FORTRAN row major storage order of arrays.
Implementation of recursion simulation: stack pointer
-----------------------------------------------------
Our replacement for the stack pointer is an INTEGER variable holding
the value of the 'call depth', with possible values ranging from 1
(first simulated activation) to MAXACT.
On starting a new simulated activation the value of the 'stack pointer',
will be incremented by 1, and used to index the modified procedure data
structures (simulated stack).
Implementation of recursion simulation: entry point
---------------------------------------------------
After passing the simulated entry point, all variables are read from
the simulated stack. This step is necessary, as program control can
flow to the entry point from the 'exit point' (the conditional GOTO
at the end of the code).
If the exit point transfers control to the entry point, we have to
read the variables from the stack using the decremented stack-pointer,
the current values are no more good.
The scheme can be improved to skip reading the variables if the
current values are valid, i.e. the stack-pointer was not decremented.
Implementation of recursion simulation: recursive call
------------------------------------------------------
Instead of a 'recursive' CALL statement we will use a series of
FORTRAN statements:
1) Incrementing the stack-pointer by 1.
2) Several assignments that will store all variables on the
stack, thus creating a simulated 'activation record'.
3) Unconditional GOTO to the 'entry point'.
Implementation of recursion simulation: exit point
--------------------------------------------------
Recursion (simulated or not) must stop sometimes, the call depth may
go up and down while executing, but in the end it must drop below 1.
The natural exit point is at the end of the code, reaching the end
means we finished an activation, so we decrement the stack-pointer.
If the stack-pointer is zero, it means everything is over, otherwise
we loop again to the entry point.
Implementation of recursion simulation: termination condition
-------------------------------------------------------------
We exit the recursion when the call depth (value of stack-pointer)
drops below 1, something in the computation have to make the call
depth eventually drop to zero.
The termination condition of the recursion is a delicate matter,
in our blobs example we mark more and more elements of matrix B,
the marked elements keep a record of the places we have already
visited, as we don't visit places we have already visited, we avoid
the trap of going after blob points in circles.
That is a subtle and important problem in multi-dimensional searches,
because we manage to avoid it with the help of the history matrix B,
we will eventually get to the end of the recursion.
Example: Identifying 'blobs'
----------------------------
MATRIX(M,N) is the input array, elements larger than TRSH are 'blob'
pixels, the output array is BLOBS(M,N), when the double loop completes,
every element in BLOBS will contain the serial number of the 'blob' it
belongs to (or stay zero).
MAXSTACK should be raised if necessary, it should be on the order
of M*N, to allow large blobs.
This is a corrected version of the procedure, to be more portable
and understandable it was made a bit longer than necessary.
C ------------------------------------------------------------------
C | Procedure: Identify and mark "blobs" in a matrix.
C | Input is matrix A, matrix B gives for each point,
C | the serial number of the blob it belongs to.
C | Author: Abraham Agay
C | Update:
C ------------------------------------------------------------------
SUBROUTINE BLOBER(MATRIX, BLOBS, M, N, TRSH, CURBLB)
IMPLICIT NONE
C ------------------------------------------------------------------
INTEGER
* M, N, BLOBS(M,N), CURBLB,
* I, J, II, JJ,
* SP, MAXSTACK
REAL MATRIX(M,N), TRSH
PARAMETER (MAXSTACK = 100)
INTEGER STACK(2,MAXSTACK)
LOGICAL NEWGOOD, GOAHEAD
C ------------------------------------------------------------------
NEWGOOD(I,J) = (MATRIX(I,J) .GE. TRSH) .AND. (BLOBS(I,J) .EQ. 0)
C ==================================================================
CURBLB = 0
DO J = 1, N
DO I = 1, M
BLOBS(I,J) = 0
ENDDO
ENDDO
C ------------------------------------------------------------------
DO J = 1, N
DO I = 1, M
IF (.NOT. NEWGOOD(I,J)) GOTO 200
II = I
JJ = J
SP = 0
CURBLB = CURBLB + 1
GOAHEAD = .TRUE.
C ------------------------------------------------------------------
100 CONTINUE
IF (GOAHEAD) THEN
SP = SP + 1
IF (SP .GT. MAXSTACK) STOP 'BLOBER: Increase stack size! '
STACK(1,SP) = II
STACK(2,SP) = JJ
IF (MATRIX(II,JJ) .GE. TRSH) BLOBS(II,JJ) = CURBLB
ELSE
SP = SP - 1
IF (SP .LE. 0) GOTO 200
II = STACK(1,SP)
JJ = STACK(2,SP)
GOAHEAD = .TRUE.
ENDIF
C ------------------------------------------------------------------
IF (II .LT. M) THEN
IF (NEWGOOD(II+1,JJ)) THEN
II = II + 1
GOTO 100
ENDIF
ENDIF
C ------------------------------------------------------------------
IF (JJ .LT. N) THEN
IF (NEWGOOD(II,JJ+1)) THEN
JJ = JJ + 1
GOTO 100
ENDIF
ENDIF
C ------------------------------------------------------------------
IF (II .GT. 1) THEN
IF (NEWGOOD(II-1,JJ)) THEN
II = II - 1
GOTO 100
ENDIF
ENDIF
C ------------------------------------------------------------------
IF (JJ .GT. 1) THEN
IF (NEWGOOD(II,JJ-1)) THEN
JJ = JJ - 1
GOTO 100
ENDIF
ENDIF
C ------------------------------------------------------------------
GOAHEAD = .FALSE.
GOTO 100
C ------------------------------------------------------------------
200 CONTINUE
ENDDO
ENDDO
RETURN
END
By the way, there is a good non-recursive algorithm by Yoav Levy
of the Hebrew University of Jerusalem (mailto:yoavl@vms.huji.ac.il).
Bibliography
------------
On simulating recursion:
Data structures using Pascal (2nd edition)
Aaron M. Tenenbaum, Moshe J. Augenstein
Prentice-Hall 1986
ISBN 0-13-196684-7
On computer architecture:
Computer Organization, 3rd edition
V. Carl Hamacher, Zvonko G. Vranesic, Safwat G. Zaky
McGraw-Hill 1984
ISBN 0-07-Y66313-0 (2nd edition)
A much more important factor in the social movement than those already mentioned was the ever-increasing influence of women. This probably stood at the lowest point to which it has ever fallen, during the classic age of Greek life and thought. In the history of Thucydides, so far as it forms a connected series of events, four times only during a period of nearly seventy years does a woman cross the scene. In each instance her apparition only lasts for a moment. In three of the four instances she is a queen or a princess, and belongs either to the half-barbarous kingdoms of northern Hellas or to wholly barbarous Thrace. In the one remaining instance208— that of the woman who helps some of the trapped Thebans to make their escape from Plataea—while her deed of mercy will live for ever, her name is for ever lost.319 But no sooner did philosophy abandon physics for ethics and religion than the importance of those subjects to women was perceived, first by Socrates, and after him by Xenophon and Plato. Women are said to have attended Plato’s lectures disguised as men. Women formed part of the circle which gathered round Epicurus in his suburban retreat. Others aspired not only to learn but to teach. Arêtê, the daughter of Aristippus, handed on the Cyrenaic doctrine to her son, the younger Aristippus. Hipparchia, the wife of Crates the Cynic, earned a place among the representatives of his school. But all these were exceptions; some of them belonged to the class of Hetaerae; and philosophy, although it might address itself to them, remained unaffected by their influence. The case was widely different in Rome, where women were far more highly honoured than in Greece;320 and even if the prominent part assigned to them in the legendary history of the city be a proof, among others, of its untrustworthiness, still that such stories should be thought worth inventing and preserving is an indirect proof of the extent to which feminine influence prevailed. With the loss of political liberty, their importance, as always happens at such a conjuncture, was considerably increased. Under a personal government there is far more scope for intrigue than where law is king; and as intriguers women are at least the209 equals of men. Moreover, they profited fully by the levelling tendencies of the age. One great service of the imperial jurisconsults was to remove some of the disabilities under which women formerly suffered. According to the old law, they were placed under male guardianship through their whole life, but this restraint was first reduced to a legal fiction by compelling the guardian to do what they wished, and at last it was entirely abolished. Their powers both of inheritance and bequest were extended; they frequently possessed immense wealth; and their wealth was sometimes expended for purposes of public munificence. Their social freedom seems to have been unlimited, and they formed combinations among themselves which probably served to increase their general influence.321 The old religions of Greece and Italy were essentially oracular. While inculcating the existence of supernatural beings, and prescribing the modes according to which such beings were to be worshipped, they paid most attention to the interpretation of the signs by which either future events in general, or the consequences of particular actions, were supposed to be divinely revealed. Of these intimations, some were given to the whole world, so that he who ran might read, others were reserved for certain favoured localities, and only communicated through the appointed ministers of the god. The Delphic oracle in particular enjoyed an enormous reputation both among Greeks and barbarians for guidance afforded under the latter conditions; and during a considerable period it may even be said to have directed the course of Hellenic civilisation. It was also under this form that supernatural religion suffered most injury from the great intellectual movement which followed the Persian wars. Men who had learned to study the constant sequences of Nature for themselves, and to shape their conduct according to fixed principles of prudence or of justice, either thought it irreverent to trouble the god about questions on which they were competent to form an opinion for themselves, or did not choose to place a well-considered scheme at the mercy of his possibly interested responses. That such a revolution occurred about the middle of the fifth century B.C., seems proved by the great change of tone in reference to this subject which one perceives on passing from Aeschylus to Sophocles. That anyone should question the veracity of an oracle is a supposition which never crosses the mind of the elder dramatist. A knowledge of augury counts among the greatest benefits222 conferred by Prometheus on mankind, and the Titan brings Zeus himself to terms by his acquaintance with the secrets of destiny. Sophocles, on the other hand, evidently has to deal with a sceptical generation, despising prophecies and needing to be warned of the fearful consequences brought about by neglecting their injunctions. The stranger had a pleasant, round face, with eyes that twinkled in spite of the creases around them that showed worry. No wonder he was worried, Sandy thought: having deserted the craft they had foiled in its attempt to get the gems, the man had returned from some short foray to discover his craft replaced by another. “Thanks,” Dick retorted, without smiling. When they reached him, in the dying glow of the flashlight Dick trained on a body lying in a heap, they identified the man who had been warned by his gypsy fortune teller to “look out for a hidden enemy.” He was lying at full length in the mould and leaves. "But that is sport," she answered carelessly. On the retirement of Townshend, Walpole reigned supreme and without a rival in the Cabinet. Henry Pelham was made Secretary at War; Compton Earl of Wilmington Privy Seal. He left foreign affairs chiefly to Stanhope, now Lord Harrington, and to the Duke of Newcastle, impressing on them by all means to avoid quarrels with foreign Powers, and maintain the blessings of peace. With all the faults of Walpole, this was the praise of his political system, which system, on the meeting of Parliament in the spring of 1731, was violently attacked by Wyndham and Pulteney, on the plea that we were making ruinous treaties, and sacrificing British interests, in order to benefit Hanover, the eternal millstone round the neck of England. Pulteney and Bolingbroke carried the same attack into the pages of The Craftsman, but they failed to move Walpole, or to shake his power. The English Government, instead of treating Wilkes with a dignified indifference, was weak enough to show how deeply it was touched by him, dismissed him from his commission of Colonel of the Buckinghamshire Militia, and treated Lord Temple as an abettor of his, by depriving him of the Lord-Lieutenancy of the same county, and striking his name from the list of Privy Councillors, giving the Lord-Lieutenancy to Dashwood, now Lord Le Despencer. "I tell you what I'll do," said the Deacon, after a little consideration. "I feel as if both Si and you kin stand a little more'n you had yesterday. I'll cook two to-day. We'll send a big cupful over to Capt. McGillicuddy. That'll leave us two for to-morrer. After that we'll have to trust to Providence." "Indeed you won't," said the Surgeon decisively. "You'll go straight home, and stay there until you are well. You won't be fit for duty for at least a month yet, if then. If you went out into camp now you would have a relapse, and be dead inside of a week. The country between here and Chattanooga is dotted with the graves of men who have been sent back to the front too soon." "Adone do wud that—though you sound more as if you wur in a black temper wud me than as if you pitied me." "Wot about this gal he's married?" "Don't come any further." "Davy, it 'ud be cruel of us to go and leave him." "Insolent priest!" interrupted De Boteler, "do you dare to justify what you have done? Now, by my faith, if you had with proper humility acknowledged your fault and sued for pardon—pardon you should have had. But now, you leave this castle instantly. I will teach you that De Boteler will yet be master of his own house, and his own vassals. And here I swear (and the baron of Sudley uttered an imprecation) that, for your meddling knavery, no priest or monk shall ever again abide here. If the varlets want to shrieve, they can go to the Abbey; and if they want to hear mass, a priest can come from Winchcombe. But never shall another of your meddling fraternity abide at Sudley while Roland de Boteler is its lord." "My lord," said Edith, in her defence, "this woman has sworn falsely. The medicine I gave was a sovereign remedy, if given as I ordered. Ten drops would have saved the child's life; but the contents of the phial destroyed it. The words I uttered were prayers for the life of the child. My children, and all who know me, can bear witness that I have a custom of asking His blessing upon all I take in hand. I raised my eyes towards heaven, and muttered words; but, my lord, they were words of prayer—and I looked up as I prayed, to the footstool of the Lord. But it is in vain to contend: the malice of the wicked will triumph, and Edith Holgrave, who even in thought never harmed one of God's creatures, must be sacrificed to cover the guilt, or hide the thoughtlessness of another." "Aye, Sir Treasurer, thou hast reason to sink thy head! Thy odious poll-tax has mingled vengeance—nay, blood—with the cry of the bond." HoME古一级毛片免费观看
ENTER NUMBET 0017 riju9.net.cn www.woru0.com.cn www.sibei1.com.cn metrc.com.cn jat8.com.cn www.duxu6.com.cn www.yanwu5.net.cn 196975.org.cn aerock.com.cn 75webfind.com.cn