Hi Everybody,

Here's the paper about stack free recursion.  I'm e-mailing it to the list
partly because I sometimes delete e-mail without meaning to delete it.
This way, I won't risk losing your letters.

Warm wishes,
Bill

     (C)opyright 1995, Otto J. A. Smith (206) 385-1956 [EMAIL PROTECTED]
                                      
   �
   
   �
   
                            Stack Free Recursion
                                      
                              Otto J. A. Smith
                                      
                               Sept 29, 1995
                                      
          �
          
   Abstract: A method of building recursive functions in systems that
   don't have a data stack is presented. We illustrate its use with a
   factorial function, the towers of hanoi puzzle and a recursive line
   drawing routine which we believe is presented here for the first time.
   We reduce beautiful recursive code to unintelligible spaghetti code
   that uses less memory and sometimes is faster. This method may speed
   up simple functions but mostly it helps us to understand the nature of
   recursion and provides a method of deriving code. We also present a
   method that uses no return stack or data stack and we derive a simple
   line drawing function using the information presented herein. All of
   the code presented here is available by anonymous ftp from olympus.net
   in pub/sites/7seas under the name recurse.cpp .
   
   Introduction: In the mid seventies I was working on the MicroData
   Reality computer and operating system. This sported what would now be
   considered a primitive BASIC, but at that time was relatively
   sophisticated. It was a compiled BASIC and like many BASICs both then
   and now, it did not support recursive function calls. In that system
   it was possible for a routine to call itself but all variables passed
   were global because there was no data stack in the system.
   
   I mentioned casually to a fellow system analyst that it was easy to
   write a factorial routine recursively on the system without emulating
   a data stack. He expressed doubt that this was possible. I won a fifty
   cent bet with the following routine. The following routine does depend
   on there being a return stack in the system. Since assembly language
   systems provide return stacks, this kind of routine works well in
   assembly language. The following routine is written in C code with C++
   comments. We do not pass a parameter to the factorial routine, we set
   the parameter x as a global value. We then call factorial() to
   calculate x factorial.
   
    /* STACKLESS FACTORIAL */

int x;
.
.                               //Set x to the value you wish to find the facto
rial of.
.
int factorial()                 //Pass x as Global No data Stack
{
  int prod;
  x = x-1;                      //A function
  if(x+1 < = 0) prod = 1;
  else prod = (x+1) * factorial();      //The recursive call
  x = x+1;                              //A function inverse
return prod;
}

   Generalization: We can generalize this technique and apply it to other
   recursive functions.
   
   Note that we have commented the lines x+1 and x-1 as "A function" and
   "A function inverse" . Using functions and there inverses is a key to
   doing this kind of recursion. Note that the sequence of statements x =
   x-1 and x = x+1 executed in that order leave the value of x unchanged.
   The function i(x) = x+1 is the inverse of the function f(x) = x-1 .
   This is the key to data stackless recursion and is helpful in
   understanding regular recursion as well. The purpose of a stack in
   recursion is to create an inverse for any function by keying in time
   and space. If we have a function that is naturally invertible, that is
   if f() is a function and there exists a function i() that is its
   inverse, ( for all x, i(f(x)) = x ) and this function is used to alter
   the value of a passed variable in a recursive call, we can use the
   function and its inverse instead of a data stack. For example: given a
   f() and its inverse i() we can generate a sequence of x's . x1 = f(x),
   x2 = f(x1), x3 = f(x2) etc. We can either go backwards or forwards
   through the xi's . in other words x2 = i(x3), x1 = i(i(x3)), x =
   i(i(i(x3))) etc. We use this fact to generate a virtual data stack to
   recover old values as we exit each recursion level.
   
   If a recursive routine of a single variable is of the following form
   where f() is an invertible function with the inverse i() over the
   range of x , then it can be translated into a stack free recursive
   function.
   
/***  THIS FORM OF ROUTINE CAN BE CHANGED TO STACK FREE RECURSION ***/
/* line 1  */     function stackfree(x)
/* line 2  */     {
/* line 3  */        .
/* line 4  */        .      //Anything goes here (except x = ...)
/* line 5  */        .
/* line 6  */    ....   stackfree(f(x))       // An expression containing a rec
ursive call.
/* line 7  */        .
/* line 8  */        .      //Anything here also
/* line 9  */        .
/* line 10 */    return somevalue;
/* line 11 */    }

   Do the following:
    1. Insert x = f(x) before the statement containing the recursive call
       (before line 6)
    2. Insert x = i(x) after the statement containing the recursive call
       (after line 6)
    3. Replace stackfree(f(x)) in line 6 with stackfree() .
    4. Replace all other occurrences of x in the line containing the
       recursive call (line 6) with i(x) 
       
   Now the routine above becomes:
/* line 1  */     function stackfree()
/* line 2  */     {
/* line 3  */        .
/* line 4  */        .      //Anything goes here
/* line 5  */        .
/* line 6  */        x = f(x);
/* line 7  (was line 6)  */    ....   stackfree()       // An expression contai
ning a recursive call
/* line 8  */        x = i(x)
/* line 9  */        .
/* line 10  */        .      //Anything here also
/* line 11 */    return somevalue;
/* line 12 */    }

   Example: Convert the following routine for factorial x .
   
int factorial(x)
{
  int prod;
  if(x <= 0) prod = 1;
  else prod = x * factorial( x-1 );
  return prod;
}

   The new routine is then:
   
int x;
.
.                               //Set x to the value you wish to find the facto
rial of.
.
int factorial()                 //Pass x as Global No data Stack
{
  int prod;
  x = x-1;                      //A function
  if(x+1 < = 0) prod = 1;               //The statement here is two lines long
  else prod = (x+1) * factorial();      //The recursive call
  x = x+1;                              //A function inverse
return prod;
}

   It is easy to generalize this to functions of several variables. In
   this case every variable passed in the recursive call must have a
   unique inverse. As is traditional, "this is left as an exercise for
   the reader." This is supposed to be a short article and we want to
   cover three more subjects. First, we want to show how to completely
   corrupt a beautiful recursive routine and make it into spaghetti code
   that uses NO stack, either data or return. Second, We wish to apply
   this technique to the "Towers of Hanoi" puzzle. Third we wish to give
   an example of the derivation of a fast line drawing routine using
   these techniques.
   
   In the simple factorial routine given above, the only purpose of the
   return stack is to keep track of the number of times we have entered
   and exited the recursion. We could use a variable to count our level
   of recursion, but all we really need is an indication of when we get
   back to the outermost level. In this case we can simply save the value
   of x itself and use it to detect when we are through with the
   recursion.
   
   The following is the routine rewritten using goto's and using no
   stacks!
   
int factorial(x)        //  This entry is used once. It is not a recursive entr
y.
{                       //   Note that within this routine we treat x as a glob
al.
  int prod;             //   Same as in routine above
  int ox = x;           //   Original x

  recursive_entry:      //A label we will return too
     x = x-1;           //A function as above

     if( x < =0 ){ prod = 1; }
     else { goto recursive_entry;  return_entry:  prod = (x+1) * prod;  }

     x = x+1;           //Inverse
     if( x != ox ) goto return_entry;

    return prod;
}

   Simply by looking we can see ways to optimize this routine. We get the
   following which is surprisingly short and efficient. It is not quite
   as good as a factorial routine done with a simple loop because we have
   to decrement x all the way to zero before we can start doing the
   multiplies, but it was derived from a true recursive routine through a
   series of simple reductions. The code is not obvious. Would you like
   to see it on a test with the question "What does this code do?".
   
int factorial(x)                //Not recursive entry
{
  int prod;
  int ox = x;
  recursive_entry:              //Recursive entry
     x = x--;
     if( x<=0 ){ prod = 1; x++; }
     else { goto recursive_entry;  return_entry:  prod = (x++) * prod;  }
     if( x != ox ) goto return_entry;
     return prod;
}

    STACKLESS TOWERS OF HANOI
    
   To give an idea of the elegant solutions available with this approach
   consider the famous "Towers of Hanoi" puzzle. Briefly stated, there
   are three posts. There is a group of disks. Each disk has a hole in it
   so that it can be put over a post. All of the disks are of different
   sizes. No two disks are the same size. In the beginning of the game
   the disks are arranged in a pyramid on one of the posts so that the
   smaller disks only rest on larger ones. The problem is to move the
   disks one at a time from post to post until all the disks have been
   moved to a new post, but with the constraint that it is never a legal
   move to put a larger disk on a smaller one. The game is very old an
   steeped in lore. Tradition has it that in one of the continuing
   simulations of Armageddon at the pentagon, an algorithm similar to the
   one presented below is used to determine the exact time of the
   explosion that ends it all.
   
   There is an elegant recursive way to define a function that will solve
   this problem. In natural language the solution might be stated as
   follows. There are three towers: tower one, tower two and tower three.
   Seven disks are on tower one. If we know how to solve the problem of
   moving 6 disks from tower one to tower three, then we can solve the
   problem of moving seven disks from tower one to tower two. First we
   move the six disks from tower one to tower three. We take the
   remaining largest disk and move it from tower one to tower two. Now if
   we can move six disks from tower one to tower three, we can use the
   same algorithm to move the six disks from tower three to tower two. We
   have reduced the problem of moving seven disks to one of moving six
   disks. Similarly we can reduce the problem of moving six disks to
   moving five disks. We continue in this way until we reduce the problem
   of moving two disks to that of moving one disk. Moving one disk is
   trivial. Footnote: 
   
   We can now move any number of disks, it merely becomes a matter of
   bookkeeping. Computers are notoriously good at bookkeeping so here is
   some C++ code for the towers of Hanoi.
   
void Hanoi(int Number_of_Disks, char * fromTower, char * toTower, char * otherT
ower)
{
   if( Number_of_Disks > 0 )
   {
     Hanoi( Number_of_Disks-1, fromTower, otherTower, toTower);
     cout < < " MOVE 1 disk from " < < fromTower < < " TO " < < toTower;
     Hanoi( Number_of_Disks-1, otherTower, toTower, fromTower);
   }
}

   We invoke this function Hanoi(7,"Tower 1","Tower 2","Tower 3") and it
   prints out the instructions for moving seven disks from Tower 1 , to
   Tower 2 .
   
   Not satisfied with this elegant recursive code, we decide to write
   this routine without using the data stack.
   
   First eliminate the Number_of_Disks variable:
   
int Number_of_Disks;    //Now a global value!!
.
.
.
void Hanoi(char * fromTower, char * toTower, char * otherTower)
{
   if( Number_of_Disks > 0 )
   {
     Number_of_Disks = Number_of_Disks-1;
     Hanoi(fromTower, otherTower, toTower);
     cout < < " MOVE 1 disk from " < < fromTower < < " TO " < < toTower;
     Hanoi(otherTower, toTower, fromTower);
     Number_of_Disks = Number_of_Disks+1;
   }
}

   Then eliminate the other variables, notice that the function simply
   exchanges pointers to strings. The inverse is simply exchanging them
   back. We use a temporary variable to do this.
   
int Number_of_Disks;    //Now a global value!!
    char * fromTower,  toTower,  otherTower;
.
.
.
void Hanoi()
{
   char * TEMP;
   if( Number_of_Disks > 0 )
   {
     Number_of_Disks = Number_of_Disks-1;
         TEMP = otherTower;        //These three lines are there own inverse
         otherTower = toTower;
         toTower = TEMP;
     Hanoi();
         TEMP = otherTower;        //See above
         otherTower = toTower;
         toTower = TEMP;
     cout < < " MOVE 1 disk from " < < fromTower < < " TO " < < toTower;
         TEMP = otherTower;
         otherTower = fromTower;
         fromTower = TEMP;
     Hanoi();
         TEMP = otherTower;
         otherTower = fromTower;
         fromTower = TEMP;
     Number_of_Disks = Number_of_Disks+1;
   }
}

   We have succeeded in reducing elegant recursive code to a combination
   of spaghetti and recursion. We have succeeded in making this code
   non-data stack dependant and thereby reduced the space needed in the
   system. This code can be further reduced but we will not do so in this
   paper.
   
    A LINE DRAWING ROUTINE
    
   Let us derive a line drawing routine using these techniques. To
   simplify the problem let us assume we are starting at pixel (0,0) and
   drawing to some point (x,y) where x and y are both positive integers.
   A line is then a set of connected points (either adjacent or on a
   diagonal) that connects (0,0) and (x,y) . We will assume that (0,0)
   and (x,y) will both be included in the set of points in the line. The
   technique we will use I have never seen anywhere else. It is NOT a
   recommended technique for most applications, although it is fast. The
   lines do not meet some of the most obvious criteria for good lines but
   they appear relatively straight for most applications. They were used
   in an early 7Seas software product and no one ever complained or
   pointed out they were not generated with Bresenhams algorithm which
   for many applications is more suitable.
   
   The technique is recursive and simple. We invoke the line draw routine
   with two points (a,b) and (c,d) . We guarantee that a < c and b < d .
   Our first invocation is with a = 0, b = 0, c = x and d = y .
   Line_Draw(0,0,x,y) is how we invoke the function.
   
   Then the algorithm for Line_Draw(a,b,c,d) is:
   
    1. If (a,b) and (c,d) are the same point, then we color (a,b) and
       return, this is the termination condition. That is:

if( a==c && b==d ){ color(a,b); return; }
    2. if (a,b) and (c,d) are not the same point we draw two new lines.
       Line_Draw(a,b,w,x) and Line_Draw(y,z,c,d). w,x,y and z are
       calculated as follows where the symbol > > represents shift right,
       that is divide by 2:

  w = a+c > > 1
  x = b+d > > 1
  y = a+c+1 > > 1
  z = b+d+1 > > 1


The least significant bit is lost in the shift right operation.
The recursive line drawing routine is then:

Line_Draw(a,b,c,d)
{
  if( (a==c ) && ( b==d ) )
  {
    color(a,b);
  }
  else
  {
   Line_Draw(     a,             b,      a+c > > 1, b+d > > 1);
   Line_Draw(a+c+1 > > 1, b+d+1 > > 1,    c,           d     );
  }
  return;
}



If we wish to eliminate the data stack we need to find an inverse for  a+c > >
1, b+d > > 1, a+c+1 > > 1
 and  b+d+1 > > 1 .
The problem is that these functions do not have an inverse.  In order to find a
n inverse
we will cheat and introduce our own data stack that is one bit wide and quite s
hort.
One 32 bit unsigned integer provides enough room for a screen that is 64K by 64
K pixels.
Here is a code fragment and its inverse used to implement  a+c > > 1  and its i
nverse.

/* Code Fragment */
   c = a+c

   stack = stack < < 1;         //Times 2
   if( c & 1 ) stack = stack + 1;       //Check least significant bit
   c = c > > 1;                 //Divide by 2


/* Code Fragment Inverse */
   c = c < < 1;                 //Times by 2
   if( stack & 1 ) c = c + 1
   stack = stack > > 1;         //Divide by 2

   c = c - a




In order to make this easier to read, we will do our shifts using
a function and its inverse called  SR(x)  and  SL(x) .  We could put
all of the functions and inverses inline, but the code would
not be as readable.  Although we do make calls to  SR()  and  SL()  with argume
nts
none of the functions needs to be recursive.  The complete implementation
is then:

unsigned long stack;       //These are all global values
int a, b, c, d;
.
.
.           //Set initial values of a, b, c, d here.
.
.

int SR(X)
{
  stack = stack < < 1;
  if( X & 1 ) stack = stack + 1;
  return X > > 1;
}

int SL(X)
{
  X = X < < 1;
  if( stack & 1 ) X=X+1;
  stack = stack > > 1;
  return X;
}

Line_Draw()
{
  if( (a==c ) && ( b==d )
  {
    color(a,b);
  }
  else
  {
   d = SR(b+d);
   c = SR(a+c);
     Line_Draw(a, b, c, d);
   c = SL(c) - a;
   d = SL(d) - b;

   b = SR(b+d+1);
   a = SR(a+c+1);
     Line_Draw(a, b, c, d);
   a = SL(a)-c-1;
   b = SL(b)-d-1;
  }
  return;
}



These routines can be further reduced and improved for speed by so doing.
For instance,  SR  and  SL  are essentially the same routine and could easily
be combined.  This particular form
of a line is also easily expressed with a grammar.  Anyone interested in the ot
her work I have done
on this kind of plotting routine should contact me.
The above routine produces a remarkably symmetrical line.

    CONCLUSION:



It is possible to take some beautiful recursive routines and convert them
to a form that doesn't use the data stack.  This results in a longer,
more difficult to read routine that makes more efficient use of memory.
It is sometimes possible through further reductions to remove the return stack
making for efficient use of memory at the expense of creating true
spaghetti code.

Comments, complaints, flames and complements should be directed to
Otto

  [EMAIL PROTECTED]


Footnote:  Trivial, unless you are a Tibetan monk playing with giant pieces mad
e out of granite.
The largest piece in one such game is 20 feet wide and three feet high.  The sm
allest piece in the same
game is the size of a large washer.  When they finally move the biggest piece,
it will probably be trivial.
 Return to place in document. 


  __________________________________________________________________________


       To MathVision Inc., (formerly 7seas software) Corporate page. 

Reply via email to