[erlang-questions] Blog: Erlang Fractal Benchmark

jm jeffm@REDACTED
Wed Jun 6 02:44:03 CEST 2007


Mats Cronqvist wrote:
> 
>    so having better syntax for type guards would be a big win...
> 


I've wanted optional typing in a programming language for a while now.
It seems it's either static or dynamic which leads to the whole which
approach is better war. Using the fractal code we'd have the following
code show at the end of this email. Note the static typing is limited to
one module, it's either on or off, and that the everything in the module
is statically typed meaning that static typing is not mixed with dynamic
typing, hence variables for the function signatures are all typed. Once
the first function's types have been labeled the rest could be inferred,
but why make life difficult for the compiler writers.

The notation used here is

function :: (type, type) -> type

followed by the normal erlang code. Some examples

 eg1 :: (integer, float) -> float
 eg1(a,b) -> a + b.

 eg2 :: (integer, float) -> {float, float}
 eg2 (a, b) -> {2.0 * a, 3.0 + b}.

 eg3 :: (arec) -> record:arec
 eg3(r) -> #arec{ a = r#arec.a + 1, b = r#arec * 2.5}.

 eg4 :: (integer|float) -> float  %% compound type integer|float
 eg4(a) -> 2.5 * a.

Example for the record arec in eg3,

 -record(arec, {a :: integer, b :: float}).

There are limitation with this typing but it's only meant for those
cases where type safety or optimisation is important. Not for use in all
code at the higher levels of a program.

Jeff.


%%%%%%%% begin example code based on fractal_benchmark
%% file: frac.erl
%% The following is NOT valid erlang code
-module(frac).

-compile(static_types).

-export([iterate/2]).

iterate :: (float, float) -> float
iterate(X, Y) ->
    CR = Y - 0.5,
    CI = X,
    iter_value(CR, CI, 0.0, 0.0, 0.0, 0.0, 0).

iter_value :: (float, float, float, float, float, float, integer)
               -> integer
iter_value(_, _, _, _, _, _, I) when I > ?MAX_ITERATIONS ->
    0;
iter_value(_, _, _, ZI2, _, ZR2, I) when ZI2 + ZR2 > ?BAILOUT ->
    I;
iter_value(CR, CI, ZI, ZI2, ZR, ZR2, I) ->
    Temp = ZR * ZI,
    ZRnew = ZR2 - ZI2 + CR,
    ZInew = Temp + Temp + CI,
    iter_value(CR, CI, ZInew, ZInew * ZInew, ZRnew, ZRnew * ZRnew, I + 1).


%%% file: fractal_benchmark.erl
-module(fractal_benchmark).
-author("Jim Menard, jimm@REDACTED").
-export([run/0]).

-define(BAILOUT, 16).
-define(MAX_ITERATIONS, 1000).

%% Idea from http://www.timestretch.com/FractalBenchmark.html

run() ->
    io:format("Rendering~n"),
    statistics(runtime),
    statistics(wall_clock),
    Seq = lists:seq(-39,39),
    lists:foreach(fun(Y) ->
			  S = lists:map(fun(X) -> plot(X, Y) end, Seq),
			  io:format("~s~n", [S])
		  end, Seq),
    io:format("~n"),
    {_, Time1} = statistics(runtime),
    {_, Time2} = statistics(wall_clock),
    Sec1 = Time1 / 1000.0,
    Sec2 = Time2 / 1000.0,
    io:format("Erlang Elapsed ~p (runtime) ~p (wall clock) seconds~n",
              [Sec1, Sec2]).

plot(X, Y) ->
    case frac:iterate(X/40.0, Y/40.0) of
        0 ->
	    42;  % ASCII for *
	_ ->
	    32   % ASCII for space
    end.

%%%% end code example




More information about the erlang-questions mailing list