Since we're off-topic...
Any sequence of numbers given by a linear recurrence equation with
constant coefficients can be computed quickly using asymptotically
efficient matrix operations. In fact, the code to do this can be
derived automatically from the recurrence itself.
Here is what you get for Fibonacci (using Maple):
> re := {fib(n+2) = fib(n+1) + fib(n)}; inits := {fib(0) = 1, fib(1) = 1};
{fib(n + 2) = fib(n + 1) + fib(n)}
{fib(0) = 1, fib(1) = 1}
> gfun[rectoproc](re union inits, fib(n));
proc (n)
local i1, loc0, loc1, loc2, tmp2, tmp1, i2;
if n <= 44 then
loc0 := 1; loc1 := 1;
if n < 0 then error "index must be %1 or greater", 0
elif n = 0 then return loc0
elif n = 1 then return loc1
end if;
for i1 to n-1 do loc2 := loc0+loc1; loc0 := loc1; loc1 := loc2
end do;
loc1
else
tmp2 := Matrix(2, 2, {(1, 1) = 1, (1, 2) = 1, (2, 1) = 1, (2, 2)
= 0});
tmp1 := Vector(2, {(1) = 1, (2) = 1});
i2 := convert(n-1, base, 2);
if i2[1] = 1 then tmp1 := Vector(2, {(1) = 2, (2) = 1}) end if;
for i1 in subsop(1 = (), i2) do
tmp2 := LinearAlgebra:-MatrixMatrixMultiply(tmp2, tmp2);
if i1 = 1 then tmp1 :=
LinearAlgebra:-MatrixVectorMultiply(tmp2, tmp1) end if
end do;
tmp1[1]
end if
end proc
Direct computation is done for small n, and then asymptotically fast
linear algebra is used for larger n.
This should be a nice Template Haskell exercise.
Jacques
Sebastian Fischer wrote:
[continuing off topic]
On Aug 16, 2010, at 3:13 PM, Daniel Fischer wrote:
You can calculate the n-th Fibonacci number in O(log n) steps using
Integer
arithmetic to get correct results.
Yes, I was delighted when I saw this for the frist time. It works be
computing
/1 1\^n
\1 0/
(This is meant to be a matrix to the nth power) by repeated squaring.
Wikipedia knows the details:
http://en.wikipedia.org/wiki/Fibonacci_number#Matrix_form
My Haskell implementation of this approach is on Hackage:
http://hackage.haskell.org/package/fibonacci
and github:
http://github.com/sebfisch/fibonacci/blob/master/Data/Numbers/Fibonacci.hs
With this implementation, printing the result of a call to, say
fib 100000000
takes *much* longer than computing it.
[almost on topic again]
I am a bit concerned about the memory usage. If you know how to fix
it, please send me patches (ideally via github)!
Cheers,
Sebastian
_______________________________________________
Haskell-Cafe mailing list
Haskell-Cafe@haskell.org
http://www.haskell.org/mailman/listinfo/haskell-cafe