-module(integral).
-export([simpson/4, simpson/3, psimpson/4, psimpson/3, sum/3, psum/3]).
-compile([native]).
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% exports API
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-spec(simpson/4 :: (From :: float(), To :: float(), N :: integer(), Func :: function()) -> float()).
-spec(psimpson/4 :: (From :: float(), To :: float(), N :: integer(), Func :: function()) -> float()).
-spec(sum/3 :: (I :: integer(), N :: integer(), Func :: function()) -> float()).
-spec(psum/3 :: (I :: integer(), N :: integer(), Func :: function()) -> float()).
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% internal API
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-spec(up_to_even/1 :: (N :: integer()) -> integer()).
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% implementation
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
simpson(From, To, Func) ->
simpson(From, To, 1000, Func).
simpson(From, To, N, Func) when N > 2 ->
if
From < To -> simpson_no_safe(From, To, up_to_even(N), Func, fun sum/3);
From > To -> - simpson_no_safe(To, From, up_to_even(N), Func, fun sum/3);
From == To -> 0.0
end.
psimpson(From, To, Func) ->
psimpson(From, To, 1000, Func).
psimpson(From, To, N, Func) when N > 2 ->
if
From < To -> simpson_no_safe(From, To, up_to_even(N), Func, fun psum/3);
From > To -> - simpson_no_safe(To, From, up_to_even(N), Func, fun psum/3);
From == To -> 0.0
end.
simpson_no_safe(From, To, N, Func, Sum) ->
Step = (To - From) / N,
Result = 2.0 * Sum(1, N div 2 - 1, fun(I) -> Func(From + 2.0 * I * (To - From) / N) end) +
4.0 * Sum(1, N div 2, fun(I) -> Func(From - Step + 2.0 * I * (To - From) / N) end) +
Func(From) + Func(To),
Result * Step / 3.0.
up_to_even(N) when is_integer(N) ->
N + (N rem 2).
sum(I, N, Func) ->
rec_sum(I, N, Func, 0.0).
rec_sum(N, N, Func, Result) ->
Func(N) + Result;
rec_sum(I, N, Func, Result) ->
rec_sum(I + 1, N, Func, Func(I) + Result).
for(N, N, Func) ->
Func(N);
for(I, N, Func) ->
Func(I),
for(I + 1, N, Func).
psum(I, N, Func) ->
S = self(),
Id = make_ref(),
for(I, N, fun(Arg) -> spawn(fun() -> S ! {calculate_complete, Id, Func(Arg)} end) end),
sum(I, N, fun(_) -> receive {calculate_complete, Id, Value} -> Value end end).