% 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));
}
/* 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);
}
/* 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".
*/
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);
}