First this erlang module is called 'prime':
-module(prime).
The method named 'test' with no argument is public
-export([test/0]).
The method named 'start' creates a new thread for the function 'loop'. It returns the ID of this new thread.
start()-> spawn(fun loop/0).
The 'loop' method waits for a message in a child process. When it receives a message matching the pattern
'{ _From, {prime,Number},Start }'
it invokes the recursive function is_prime and prints the result:loop()->
receive
{ _From, {prime,Number},Start }->
io:format("result=~p\n Process-ID=~p\n Duration=~p ~n",[
is_prime(2,Number),
self(),
timer:now_diff(now(),Start)/1.0e6
])
;
{_From,_Other} ->
io:format("Booomm~n",[])
end.
receive
{ _From, {prime,Number},Start }->
io:format("result=~p\n Process-ID=~p\n Duration=~p ~n",[
is_prime(2,Number),
self(),
timer:now_diff(now(),Start)/1.0e6
])
;
{_From,_Other} ->
io:format("Booomm~n",[])
end.
The function 'is_prime' is a simple-and-stupid recursive method testing if a number is a prime where we search if the numbers 'Div' lower than 'N' have a modulus of 'Number/Div=0':
is_prime(Div,Number)->
if
Div =:= Number -> {result,{number,Number},{prime,true}};
Number rem Div =:= 0 -> {result,{number,Number},{prime,false}};
true-> is_prime(Div+1,Number)
end.
if
Div =:= Number -> {result,{number,Number},{prime,true}};
Number rem Div =:= 0 -> {result,{number,Number},{prime,false}};
true-> is_prime(Div+1,Number)
end.
The method named 'rpc' sends the ID of the current process, the prime number and the current system time to the child process:
rpc(Pid,Request)->
Pid ! { self(), Request , now()}
.
Pid ! { self(), Request , now()}
.
The 'test' method creates a list 'NUMS' of numbers. For each number N in this list the function prime:start is called and it returns a new thread-ID. This Thread-ID is sent with 'N' to the function rpc.
test()->
NUMS=[111, 197951153,197951154,102950143,65537,3,7,8,12],
lists:foreach( fun(N)-> Pid= start(), rpc(Pid,{prime,N}) end, NUMS )
.
NUMS=[111, 197951153,197951154,102950143,65537,3,7,8,12],
lists:foreach( fun(N)-> Pid= start(), rpc(Pid,{prime,N}) end, NUMS )
.
All in one, here is the full code:
-module(prime).
-export([test/0]).
start()-> spawn(fun loop/0).
rpc(Pid,Request)->
Pid ! { self(), Request , now()}
.
loop()->
receive
{ _From, {prime,Number},Start }->
io:format("result=~p\n Process-ID=~p\n Duration=~p ~n",[
is_prime(2,Number),
self(),
timer:now_diff(now(),Start)/1.0e6
])
;
{_From,_Other} ->
io:format("Booomm~n",[])
end.
is_prime(Div,Number)->
if
Div =:= Number -> {result,{number,Number},{prime,true}};
Number rem Div =:= 0 -> {result,{number,Number},{prime,false}};
true-> is_prime(Div+1,Number)
end.
test()->
NUMS=[111, 197951153,197951154,102950143,65537,3,7,8,12],
lists:foreach( fun(N)-> Pid= start(), rpc(Pid,{prime,N}) end, NUMS )
.
-export([test/0]).
start()-> spawn(fun loop/0).
rpc(Pid,Request)->
Pid ! { self(), Request , now()}
.
loop()->
receive
{ _From, {prime,Number},Start }->
io:format("result=~p\n Process-ID=~p\n Duration=~p ~n",[
is_prime(2,Number),
self(),
timer:now_diff(now(),Start)/1.0e6
])
;
{_From,_Other} ->
io:format("Booomm~n",[])
end.
is_prime(Div,Number)->
if
Div =:= Number -> {result,{number,Number},{prime,true}};
Number rem Div =:= 0 -> {result,{number,Number},{prime,false}};
true-> is_prime(Div+1,Number)
end.
test()->
NUMS=[111, 197951153,197951154,102950143,65537,3,7,8,12],
lists:foreach( fun(N)-> Pid= start(), rpc(Pid,{prime,N}) end, NUMS )
.
Compiling:
erlc prime.erl
Running:
erl -noshell -s prime test
Result (as you can see, the biggest prime appears at the end of the list because it took more time for the calculation):
result={result,{number,65537},{prime,true}}
Process-ID=<0.34.0>
Duration=0.006522
result={result,{number,111},{prime,false}}
Process-ID=<0.30.0>
Duration=7.6e-5
result={result,{number,197951154},{prime,false}}
Process-ID=<0.32.0>
Duration=4.57e-4
result={result,{number,3},{prime,true}}
Process-ID=<0.35.0>
Duration=7.25e-4
result={result,{number,7},{prime,true}}
Process-ID=<0.36.0>
Duration=7.23e-4
result={result,{number,8},{prime,false}}
Process-ID=<0.37.0>
Duration=7.22e-4
result={result,{number,12},{prime,false}}
Process-ID=<0.38.0>
Duration=7.2e-4
result={result,{number,102950143},{prime,true}}
Process-ID=<0.33.0>
Duration=8.856508
result={result,{number,197951153},{prime,true}}
Process-ID=<0.31.0>
Duration=49.51542
Process-ID=<0.34.0>
Duration=0.006522
result={result,{number,111},{prime,false}}
Process-ID=<0.30.0>
Duration=7.6e-5
result={result,{number,197951154},{prime,false}}
Process-ID=<0.32.0>
Duration=4.57e-4
result={result,{number,3},{prime,true}}
Process-ID=<0.35.0>
Duration=7.25e-4
result={result,{number,7},{prime,true}}
Process-ID=<0.36.0>
Duration=7.23e-4
result={result,{number,8},{prime,false}}
Process-ID=<0.37.0>
Duration=7.22e-4
result={result,{number,12},{prime,false}}
Process-ID=<0.38.0>
Duration=7.2e-4
result={result,{number,102950143},{prime,true}}
Process-ID=<0.33.0>
Duration=8.856508
result={result,{number,197951153},{prime,true}}
Process-ID=<0.31.0>
Duration=49.51542
That's it.
Pierre.
Hi
ReplyDeleteHere my try based on Oneill's
paper: http://www.cs.hmc.edu/~oneill/papers/Sieve-JFP.pdf
% "Genuine" Erathostenes sieve in erlang
% based on http://www.cs.hmc.edu/~oneill/papers/Sieve-JFP.pdf
% 2009 Angel Alvarez
%
Thsi is a sieve where the cells are processes that are created in a lazy fashion as needed, and avoid duplicate crossing off of multiples.
You can reach me at erlang-questions list...
Regards Angel
-module(multi_erathostenes).
-author("angel at uah.es").
-export([start/1,worker/1]).
-record(cell, {prime,upperbound}).
compare(X,Y) when X > Y -> greater;
compare(X,Y) when X < Y -> smaller;
compare(_,_) -> equal.
worker(#cell{prime=Prime,upperbound=UpperBound} = Cell)->
receive
{test,Number,ParentPID} ->
ParentPID ! ok,
case compare(Number,UpperBound) of
equal ->
%% io:format("[Worker of prime: ~w (~w)] Found composite: ~w~n",[Prime,UpperBound,Number]),
worker( Cell#cell{upperbound= UpperBound + Prime});
smaller ->
io:format("[last_worker] Found Prime: ~w~n",[Number]),
%% io:format("~w~n",[Prime]),
NextPID =spawn(?MODULE,worker,[#cell{ prime= Number,upperbound=Number*Number}]),
worker(Cell,NextPID)
end;
stop ->
%% io:format("~n",[])
noop
end.
worker(#cell{prime=Prime,upperbound=UpperBound} = Cell,NextPID) ->
receive
{test,Number,ParentPID} ->
ParentPID ! ok,
case compare(Number,UpperBound) of
equal ->
%% io:format("[Worker of prime: ~w (~w)] Found composite: ~w~n",[Prime,UpperBound,Number]),
worker( Cell#cell{upperbound= UpperBound + Prime},NextPID);
smaller ->
%% io:format("[Worker of prime: ~w (~w)] passing along: ~w~n",[Prime,UpperBound,Number]),
NextPID ! {test,Number,self()},
receive
ok -> ok
end,
worker(Cell,NextPID);
greater ->
%% io:format("[Worker of prime: ~w (~w)] passing along: ~w~n",[Prime,UpperBound,Number]),
NextPID ! {test,Number,self()},
receive
ok -> ok
end,
worker( Cell#cell{upperbound= UpperBound + Prime},NextPID)
end;
stop ->
NextPID ! stop,
noop
end.
start([N|_StrCommand]) when is_list(N) ->
start(list_to_integer(N));
start(N) ->
OnePID=spawn(?MODULE,worker,[#cell{prime=2,upperbound=4}]),
%% io:format("~w~n",[2]),
cicle(3,N,OnePID).
cicle(Last,Last,Worker) ->
Worker ! stop;
cicle(Current,Last,Worker) ->
Worker ! {test,Current,self()},
receive
ok -> ok
end,
cicle(Current+1,Last,Worker).