Skip to content

Instantly share code, notes, and snippets.

@atrolla
Created January 12, 2017 08:47
Show Gist options
  • Save atrolla/965405f90023039dc1105af624ca80f6 to your computer and use it in GitHub Desktop.
Save atrolla/965405f90023039dc1105af624ca80f6 to your computer and use it in GitHub Desktop.
-module(pi).
-author("Yvan").
-export([approximatePi/2,startCalculate/1,mapApproximatePi/0,reduce/3]).
mapApproximatePi() ->
receive
{Level, Range, Reducer} ->
Approx = approximatePi(Level,Range),
%io:format("approximate ! ~w = (~w,~w) :~w~n",[self(),Level,Range,Approx]),
Reducer ! {Approx, self()}
end.
reduce(AccResult, 0, Summonner) ->
Summonner ! AccResult;
reduce(AccResult, Workers, Summonner) ->
receive
{Approximation, Pid} ->
%io:format("Received from ~w : ~w~n",[Pid, Approximation]),
reduce(Approximation + AccResult, Workers-1, Summonner)
end.
startCalculate(ToLevel) ->
Range = 5,
CreateWorkers = fun Func(Acc,X,R) when X-R >= 1 -> Func([{X-R,R}|Acc], X-R, R);
Func(Acc,1,_) -> Acc;
Func(Acc,X,_) -> [{1,X}|Acc]
end,
Workers = CreateWorkers([],ToLevel+1,Range),
Reducer = spawn(?MODULE, reduce, [0,length(Workers),self()]),
io:format("Workers:~w~n",[length(Workers)]),
F = fun ({Lvl,Rng}) ->
%io:format("Start Workers:(Level:~w/Range:~w)~n",[Lvl,Rng]),
spawn(?MODULE, mapApproximatePi, []) ! {Lvl, Rng, Reducer}
% done
end,
lists:foreach(F,Workers),
%Reducer ! {4, self()},
%spawn(?MODULE, mapApproximatePi, []) ! {1, 3, self()},
receive
Result -> Result
end.
%4.
approximatePi(_, 0) -> 0;
approximatePi(Level, Range) when abs(Range-Level) rem 2 =:= 1 ->
N = (-4 / (2 * (Range + Level - 2) + 1)),
%io:format("(L:~w,R:~w)1 = ~w~n",[Level,Range,N]),
N + approximatePi(Level, Range-1);
approximatePi(Level, Range) when abs(Range-Level) rem 2 =:= 0 ->
N = 4 / (2 * (Range + Level - 2) + 1),
%io:format("(L:~w,R:~w)0 = ~w~n",[Level,Range,N]),
N + approximatePi(Level, Range-1).
@Arnauld
Copy link

Arnauld commented Jan 12, 2017

To allow tail recursion, you should avoid non terminal expression N + approximatePi(Level, Range-1)
e.g. replace it with an accumulator approximatePi(Acc + N, Level, Range-1)

approximatePi(Acc, _, 0) -> Acc;
approximatePi(Acc, Level, Range) when abs(Range-Level) rem 2 =:= 1 -> 
  ...,
  approximatePi(Acc + N, Level, Range-1);
approximatePi(Acc, Level, Range) -> 
  ...,
  approximatePi(Acc + N, Level, Range-1);

no need for the guard in the third case: redundant with the odd one.

CreateWorkers is hard to read

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment