/** This is a collection of simple implementations of factorial. Compile them into assembly to see how these are translated into machine instructions. to compile: gcc -S 12-factorial.c Change the optimization level [-Og, -O1, -O2] to see how the compiler changes the code. **/ /* Standarad recursive implementation Note that the assembly has a lot of overhead in terms of instructions dedicated to stack management If you crank the optimization up to -O2, the compiler will optimize out the recursion. */ int factorialRecursive(int x){ if (x <= 1){ return 1; } else{ return x * factorialRecursive(x - 1); } } /* Simple loop approach See how many fewer instructions it runs */ int factorialLoop(int x){ int result = 1; while(x > 1){ result *= x; x--; } return result; } /* For more complex recursion, the compiler will not be able to optimize out the recursion. We can help by making the recursion "tail recursion". This is recursion that does no additional operations after the recursive call. Since there is nothing more to do, there is no need to preserve the stack frame. For functions like factorial that accumulate a value, we can use a strategy called "bucket recursion" to force tail recursion. The idea is to acculmulate down by passing the current accumulation as an argument. This typically requires you to write an additional function that hides the use of this accumululator. */ int factorialBucketHelper(int x, int answer){ if (x <= 1){ return answer; }else{ return factorialBucketHelper(x-1, x* answer); } } int factorialBucket(int x){ return factorialBucketHelper(x, 1); }