next up previous contents
Next: Trees: ADT Up: Recursion Previous: Recursion   Contents

Factorial: fact [45]

% gcc -o fact fact.c                                  > tcc fact.c
% fact
> h
h(elp; q(uit; i(terative x; r(ecursive x; t(ail x; g(oto x; s(tack x

Data File with Test Cases: fact.dat

i 3 r 3 t 3 g 3 s 3

% fact fact.dat
Iterative factorial of 3: 6
Recursive factorial of 3: 6
Tail recusive factorial of 3: 6
Goto factorial of 3: 6

push 3; push 0; push 2; push 0; push 1; push 0; push 0; push 0; 
pop 0; pop 0; push 1; pop 1; pop 0; pop 1; push 1; pop 1; pop 0; 
pop 2; push 2; pop 2; pop 0; pop 3; push 6; pop 6; 

Stack factorial of 3: 6



Recursion: fact.c [46]

/* A standard ITERATIVE factorial function. */

int iterative_factorial(int i) {
int f;
  f = 1;
  while (i != 0) {
    f = i * f;
    i--;
  }
  return(f);
}

/* A RECURSIVE factorial function. Note that the WHILE loop in the
   ITERATIVE version is now an IF statement of the NEGATIVE.  */

int recursive_factorial(int i) {
  if (i == 0)
    return(1);
  else
    return(i * recursive_factorial(i-1));
}


Arrays: fact.c [47]
/* The RECURSIVE version rewritten. Note that this is TAIL recursion which
   shows that this should not really be a recursive algorithm.  */

int tail_factorial(int i) {
int f = 1;
  if (i != 0)
    f = i * tail_factorial(i-1);
  return(f);
}

/* TAIL RECURSION can be eliminated mechanically with a GOTO the START and
   an ASSIGNMENT of the PARAMETER value (i-1) to the LOCAL variable (i).
   Another way is to change the IF to a WHILE of the negative. */

int goto_factorial(int i) {
int f = 1;
  start:
  if (i != 0) {
    f = i * f;
    i = i - 1;
    goto start;
  }
  return(f);
}


Arrays: fact.c [48]
/* RECURSION creates a STACK of the local variables. In this function
   the recursion is eliminated and the variables are stacked. Again,
   the factorial function should be ITERATIVE without a stack or recursion.

   On call to a function : push on local (and parameter) variables
   On exit (return)      : save the return (ret) value
                           pop off REMAINING local variables
                           push on the return value
   On return from call   : pop off the return value
                           pop off to restore local variables

   NOTE: A compiler could restore a BASE address of the local variables
         and then reference all of the locals from this BASE. This is
         indexing into the STACK. This would eliminate the "pop off
         to restore". Then, ANY return, would be treated the same: "pop
         off ALL local variables".
*/


Arrays: fact.c [49]
int stack_factorial(int i) {
STACK S  = create_stack(); int f = 1; int ret;     STACK:
  push(i,S);                push 3;                STACK: 3
  push(f,S);                push 1;                STACK: 3 1
  while (i != 0) {
    i = i-1;
    push(i,S);              push 2; push 1; push 0;
    push(f,S);              push 1; push 1; push 1; 
  }                                                STACK: 3 1 2 1 1 1 0 1
  ret = f;
  pop(S);                   pop 1;                 STACK: 3 1 2 1 1 1 0
  pop(S);                   pop 0;                 STACK: 3 1 2 1 1 1 
  while (!is_empty(S)) {
    push(ret,S);            push 1; push 1; push 2;
    ret = pop(S);           pop 1;  pop 1;  pop 2;
    f = pop(S);             pop 1;  pop 1;  pop 1;
    i = pop(S);             pop 1;  pop 2;  pop 3
    f = i * ret;
    ret = f;
  }                                                STACK:
  push(ret,S);              push 6;                STACK: 6
  ret = pop(S);             pop 6;                 STACK: 
  return(f);
}



Ted Billard 2001-10-25