diff --git a/primes.erl b/primes.erl index 7031f2c..8753adf 100644 --- a/primes.erl +++ b/primes.erl @@ -4,7 +4,9 @@ -module(primes). -compile(export_all). -primes(Prime, Max, Primes,Integers) when Prime > Max -> +% Idiomatic Erlang Sieve of Erathosthenes + +primes(Prime, Max, Primes, Integers) when Prime > Max -> lists:reverse([Prime|Primes]) ++ Integers; primes(Prime, Max, Primes, Integers) -> @@ -14,15 +16,66 @@ primes(Prime, Max, Primes, Integers) -> primes(N) -> primes(2, round(math:sqrt(N)), [], lists:seq(3,N,2)). % skip odds +% Clone with array + +primes_a(N) when N < 2 -> []; +primes_a(N) when N == 2 -> [ 2 ]; +primes_a(N) -> + Mroot = trunc(math:sqrt(N)), + S = filter_primes_a(0, Mroot, 1 + (N-3) div 2, array:from_list(lists:seq(3, N, 2))), + [2 | [X || X <- array:to_list(S), X =/= 0]]. + +filter_primes_a(I, Mroot, _Half, S) when 2*I+3 > Mroot -> S; +filter_primes_a(I, Mroot, Half, S) -> + M = 2*I+3, + E = array:get(I, S), + if + E > 0 -> filter_primes_a(I+1, Mroot, Half, set_0a((M*M-3) div 2, M, Half, S)); + E == 0 -> filter_primes_a(I+1, Mroot, Half, S) + end. + +set_0a(J, _M, Jmax, S) when J >= Jmax -> S; +set_0a(J, M, Jmax, S) -> + set_0a(J+M, M, Jmax, array:set(J, 0, S)). + +% Clone with ets + +primes_s(N) when N < 2 -> []; +primes_s(N) when N == 2 -> [ 2 ]; +primes_s(N) -> + Mroot = trunc(math:sqrt(N)), + Seq = lists:seq(0, (N-3) div 2, 1), + S = ets:new(tab, [ordered_set]), + lists:foreach(fun(I) -> ets:insert(S, {I, 3+I*2}) end, Seq), + filter_primes_s(0, Mroot, 1 + (N-3) div 2, S), + ets:foldr(fun(E, A) -> [element(2,E)|A] end, [2], S). + +filter_primes_s(I, Mroot, _Half, _S) when 2*I+3 > Mroot -> ok; +filter_primes_s(I, Mroot, Half, S) -> + M = 2*I+3, + E = ets:lookup(S, I), + if + length(E) > 0 -> set_0s((M*M-3) div 2, M, Half, S), filter_primes_s(I+1, Mroot, Half, S); + length(E) == 0 -> filter_primes_s(I+1, Mroot, Half, S) + end. + +set_0s(J, _M, Jmax, _S) when J >= Jmax -> ok; +set_0s(J, M, Jmax, S) -> + ets:delete(S, J), + set_0s(J+M, M, Jmax, S). + +% All of the above are almost equal and shitty anyway (~40 times slower than nodejs, ~100 times slower than C++) + print_times(T, N) -> io:format("Erlang: ~p iterations in ~p seconds = ~p seconds per 30 iterations~n", [N, T, T*30.0/N]). start(T, N) -> lists:foreach( fun(_) -> - io:format("Found ~p primes~n", [length(primes(10000000))]) + P = primes(10000000), + io:format("Found ~p primes~n", [length(P)]) end, lists:seq(1, N)), print_times((os:system_time(millisecond)-T)/1000, N). main() -> - start(os:system_time(millisecond), 5). + start(os:system_time(millisecond), 2).