-module(tp1_correction). %% ---------------------------------------------------------------------------- -export([max/1, perimeter/1, sort/1]). -export([map/2, partial/2, multimap/2]). -export([multispawn/1, dreturn/2]). -export([delegate/1, test_delegate/0]). -export([dgeneric/4]). -export([dmax/2, benchmark_dmax/1]). -export([dsort/2, benchmark_dsort/1]). %% ---------------------------------------------------------------------------- max([] ) -> throw(invalid_arg); max([H] ) -> H; max([H|T]) -> erlang:max(H,max(T)). perimeter({square, Side} ) -> 4*Side; perimeter({circle, Radius} ) -> 2*math:pi()*Radius; perimeter({triangle, A, B, C}) -> A+B+C; perimeter(_ ) -> throw(invalid_arg). insert(E, [] ) -> [E]; insert(E, [H|T]) when H [H|insert(E,T)]; insert(E, [H|T]) -> [E,H|T]. sort([] ) -> []; sort([H|T]) -> insert(H, sort(T)). %% ---------------------------------------------------------------------------- map(_, [] ) -> []; map(F, [H|T]) -> [F(H)| map(F,T)]. partial(F,P) -> fun(X) -> F(P,X) end. % usage: (tp1:partial(fun erlang:max/2, 1))(2). multimap(F,L) -> map(partial(fun map/2,F), L). %% ---------------------------------------------------------------------------- multispawn(L) -> map(fun ({M,F,L}) -> erlang:spawn(M,F,L) end, L). % dreturn(Pid, {M,F,L}) -> Pid!{erlang:apply(M, F, L), erlang:self()}. dreturn(Pid, {M,F,L}) -> erlang:send(Pid, {erlang:apply(M, F, L), erlang:self()}). %% ---------------------------------------------------------------------------- delegate(L) -> map( fun(S) -> receive {A, S} -> A end end, multispawn( map( fun(C) -> {tp1, dreturn, [erlang:self(), C]} end, L ) ) ). test_delegate() -> delegate([ {erlang, min, [1,2]}, {erlang, max, [1,2]}, {io, fwrite, ["hello ~s !~n", ["world"]]} ]). %% ---------------------------------------------------------------------------- dgeneric(Input, Threshold, BlockOperation, MergeOperation) -> case erlang:length(Input) of Length when Length > Threshold -> apply(MergeOperation, delegate( map( fun(SubList) -> {tp1, dgeneric, [SubList, Threshold, BlockOperation, MergeOperation]} end, erlang:tuple_to_list(lists:split(Length div 2, Input)) ) ) ); _ -> BlockOperation(Input) end. %% ---------------------------------------------------------------------------- dmax(L, Threshold) -> dgeneric(L, Threshold, fun lists:max/1, fun erlang:max/2). %% ---------------------------------------------------------------------------- merge([], Ls2 ) -> Ls2; merge(Ls1, [] ) -> Ls1; merge([H1|T1], [H2|T2]) when H1 < H2 -> [H1 | merge(T1, [H2|T2])]; merge([H1|T1], [H2|T2]) -> [H2 | merge([H1|T1], T2 )]. dsort(Input, Threshold) -> dgeneric(Input, Threshold, fun lists:sort/1, fun merge/2). %% ---------------------------------------------------------------------------- benchmark(Seq, Dist, Size) -> benchmark(Seq, Dist, Size, 4). benchmark(Seq, Dist, Size, Cores) -> U = [random:uniform() || _ <- lists:seq(1, Size)], {T1, M1} = timer:tc(Seq, [U] ), {T2, M2} = timer:tc(Dist, [U, Size div Cores]), io:fwrite("seq: ~p~ndist: ~p~n", [T1, T2]), M1==M2. benchmark_dmax(Size) -> benchmark(fun lists:max/1, fun tp1:dmax/2, Size). benchmark_dsort(Size) -> benchmark(fun lists:sort/1, fun tp1:dsort/2, Size). %% ----------------------------------------------------------------------------