I asked this question to get to know how to increase the runtime call stack size in the JVM. I\'ve got an answer to this, and I\'ve also got many useful answers and comments
It is hard to give a sensible solution since you are keen to avoid all sane approaches. Refactoring one line of code is the senible solution.
Note: Using -Xss sets the stack size of every thread and is a very bad idea.
Another approach is byte code manipulation to change the code as follows;
public static long fact(int n) {
return n < 2 ? n : n > 127 ? 0 : n * fact(n - 1);
}
given every answer for n > 127 is 0. This avoid changing the source code.
Other posters have pointed out how to increase memory and that you could memoize calls. I'd suggest that for many applications, you can use Stirling's formula to approximate large n! very quickly with almost no memory footprint.
Take a gander at this post, which has some analysis of the function and code:
http://threebrothers.org/brendan/blog/stirlings-approximation-formula-clojure/
I did Anagram excersize, which is like Count Change problem but with 50 000 denominations (coins). I am not sure that it can be done iteratively, I do not care. I just know that the -xss option had no effect -- I always failed after 1024 stack frames (might be scala does bad job delivering to to java or printStackTrace limitation. I do not know). This is bad option, as explained anyway. You do not want all threads in to app to be monstrous. However, I did some experiments with new Thread (stack size). This works indeed,
def measureStackDepth(ss: Long): Long = {
var depth: Long = 0
val thread: Thread = new Thread(null, new Runnable() {
override def run() {
try {
def sum(n: Long): Long = {depth += 1; if (n== 0) 0 else sum(n-1) + 1}
println("fact = " + sum(ss * 10))
} catch {
case e: StackOverflowError => // eat the exception, that is expected
}
}
}, "deep stack for money exchange", ss)
thread.start()
thread.join()
depth
} //> measureStackDepth: (ss: Long)Long
for (ss <- (0 to 10)) println("ss = 10^" + ss + " allows stack of size " -> measureStackDepth((scala.math.pow (10, ss)).toLong) )
//> fact = 10
//| (ss = 10^0 allows stack of size ,11)
//| fact = 100
//| (ss = 10^1 allows stack of size ,101)
//| fact = 1000
//| (ss = 10^2 allows stack of size ,1001)
//| fact = 10000
//| (ss = 10^3 allows stack of size ,10001)
//| (ss = 10^4 allows stack of size ,1336)
//| (ss = 10^5 allows stack of size ,5456)
//| (ss = 10^6 allows stack of size ,62736)
//| (ss = 10^7 allows stack of size ,623876)
//| (ss = 10^8 allows stack of size ,6247732)
//| (ss = 10^9 allows stack of size ,62498160)
You see that stack can grow exponentially deeper with exponentially more stack alloted to the thread.