Is it that p is double called the majority of the calculations, thereby making the function call itself twice when a simple "save" of the result would have stopped a geometrically growing tree? I've never studied this, just curious.
Re:Recursion via Pascal
by RiderOfGiraffes on Wednesday January 12, 2011 @09:48PM
(#2098621)
Yes. Consider calling p with n=1. Then it takes one call. Now call it with n=2. It gets called twice with n=1, and you need to do the multiply. Thus T(2)=2 calls + 1 multiply.
Now call it with n=4. Time taken is 2T(2) plus a multiply. Hence T(4)=2(2c+m)+m=4c+3m.
Inductively we can prove that T(n)=n * c + m, where c is the time of a call, and m is the time of a multiply, and I'm ignoring small details.
If you save the result of a call and reuse it then you get a different result, of course, and if you really want to learn how this works then you should try to figure it out.
So what would be the operation to keep O(log n)? save p(x, n div 2) in memory?
One option would be to have the language (in this case Pascal) support a hint keyword that indicates that p is side-effect-free and doesn't modify any global data, or any data outside of its local scope. Then the compiler can use a simple common subexpression elimination optimization. The SQL 2003 standard does this with functions in order to aid the implementor's compiler/optimizer ability to optimize functions that don't modify or read any data and are purely functional.
This is the one place where "pure" functional languages have such potential. If the function is guaranteed side-effect free then the calls can be memo-ised, and this routine becomes O(lg n) "for free".