Here's an Erlang version, with lots of grains of salt added: AFAIK
Erlang doesn't provide bigint expt and sqrt, so they had to be added to
the Erlang src. And Erlang isn't exactly known for numerical
performance. With that in mind, here goes:
-module(fib).
-export([main/1]).
-mode(compile).
expt(_, 0) -> 1;
expt(A, 1) -> A;
expt(A, B) -> A * expt(A, B-1).
isqrt(Num, M, N) when abs(M - N) =< 1 ->
if N * N =< Num -> N;
true -> N - 1
end;
isqrt(Num, _, N) ->
isqrt(Num, N, (N + Num div N) div 2).
integer_sqrt(Value) when Value >= 0 -> isqrt(Value, 1, (1 + Value) div 2).
short_delay(Value) -> integer_sqrt(Value).
range(I, J) -> lists:seq(I, J-1).
tfib(0, GV) -> short_delay(GV), 1;
tfib(1, GV) -> short_delay(GV), 1;
tfib(N, GV) ->
short_delay(GV),
Pid = self(),
spawn(fun() -> Pid ! tfib(N-2, GV) end),
Y = tfib(N-1, GV),
receive
Result -> Result + Y
end.
goloop(0) -> ok;
goloop(ThreadsRemaining) ->
receive
_ -> goloop(ThreadsRemaining - 1)
end.
go(N, Repeat, Granularity) ->
Pid = self(),
GV = expt(11, Granularity),
Threads = [spawn(fun() -> Pid ! tfib(N, GV) end) || _ <- range(0, Repeat)],
goloop(length(Threads)).
main(_) ->
go(15, 100, 0),
go(15, 20, 1001).
$ time escript fib.erl
real 1m22.728s
user 7m54.460s
sys 0m0.396s
Ran on a six-core machine, Erlang used up all cores up to nearly 100%.
Leif