Current section

Files

Jump to
gleam_stats src gleam_stats@math.erl
Raw

src/gleam_stats@math.erl

-module(gleam_stats@math).
-compile(no_auto_import).
-export([acos/1, acosh/1, asin/1, asinh/1, atan/1, atan2/2, atanh/1, ceil/1, cos/1, cosh/1, exp/1, floor/1, log/1, log10/1, log2/1, pow/2, sign/1, sin/1, sinh/1, tan/1, tanh/1, to_degrees/1, to_radians/1, beta/2, erf/1, gamma/1, gammainc/2, round/2, combination/2, factorial/1, permutation/2, pi/0, tau/0]).
-spec acos(float()) -> {ok, float()} | {error, binary()}.
acos(X) ->
case (X >= -1.0) andalso (X =< 1.0) of
true ->
_pipe = math:acos(X),
{ok, _pipe};
false ->
_pipe@1 = <<"Invalid input argument: x >= -1 or x <= 1. Valid input is -1. <= x <= 1."/utf8>>,
{error, _pipe@1}
end.
-spec acosh(float()) -> {ok, float()} | {error, binary()}.
acosh(X) ->
case X >= 1.0 of
true ->
_pipe = math:acosh(X),
{ok, _pipe};
false ->
_pipe@1 = <<"Invalid input argument: x < 1. Valid input is x >= 1."/utf8>>,
{error, _pipe@1}
end.
-spec asin(float()) -> {ok, float()} | {error, binary()}.
asin(X) ->
case (X >= -1.0) andalso (X =< 1.0) of
true ->
_pipe = math:asin(X),
{ok, _pipe};
false ->
_pipe@1 = <<"Invalid input argument: x >= -1 or x <= 1. Valid input is -1. <= x <= 1."/utf8>>,
{error, _pipe@1}
end.
-spec asinh(float()) -> float().
asinh(X) ->
math:asinh(X).
-spec atan(float()) -> float().
atan(X) ->
math:atan(X).
-spec atan2(float(), float()) -> float().
atan2(Y, X) ->
math:atan2(Y, X).
-spec atanh(float()) -> {ok, float()} | {error, binary()}.
atanh(X) ->
case (X > -1.0) andalso (X < 1.0) of
true ->
_pipe = math:atanh(X),
{ok, _pipe};
false ->
_pipe@1 = <<"Invalid input argument: x > -1 or x < 1. Valid input is -1. < x < 1."/utf8>>,
{error, _pipe@1}
end.
-spec ceil(float()) -> float().
ceil(X) ->
math:ceil(X).
-spec cos(float()) -> float().
cos(X) ->
math:cos(X).
-spec cosh(float()) -> float().
cosh(X) ->
math:cosh(X).
-spec exp(float()) -> float().
exp(X) ->
math:exp(X).
-spec floor(float()) -> float().
floor(X) ->
math:floor(X).
-spec log(float()) -> {ok, float()} | {error, binary()}.
log(X) ->
case X > 0.0 of
true ->
_pipe = math:log(X),
{ok, _pipe};
false ->
_pipe@1 = <<"Invalid input argument: x <= 0. Valid input is x > 0."/utf8>>,
{error, _pipe@1}
end.
-spec log10(float()) -> {ok, float()} | {error, binary()}.
log10(X) ->
case X > 0.0 of
true ->
_pipe = math:log10(X),
{ok, _pipe};
false ->
_pipe@1 = <<"Invalid input argument: x <= 0. Valid input is x > 0."/utf8>>,
{error, _pipe@1}
end.
-spec log2(float()) -> {ok, float()} | {error, binary()}.
log2(X) ->
case X > 0.0 of
true ->
_pipe = math:log2(X),
{ok, _pipe};
false ->
_pipe@1 = <<"Invalid input argument: x <= 0. Valid input is x > 0."/utf8>>,
{error, _pipe@1}
end.
-spec pow(float(), float()) -> {ok, float()} | {error, binary()}.
pow(X, Y) ->
Fractional = (ceil(Y) - Y) > 0.0,
case ((X < 0.0) andalso Fractional) orelse ((X =:= 0.0) andalso (Y < 0.0)) of
true ->
_pipe = <<"Invalid input argument: x < 0 and y is fractional or x = 0 and y < 0."/utf8>>,
{error, _pipe};
false ->
_pipe@1 = math:pow(X, Y),
{ok, _pipe@1}
end.
-spec sign(float()) -> float().
sign(X) ->
do_sign(X).
-spec do_sign(float()) -> float().
do_sign(X) ->
case X < 0.0 of
true ->
-1.0;
false ->
case X =:= 0.0 of
true ->
0.0;
false ->
1.0
end
end.
-spec sin(float()) -> float().
sin(X) ->
math:sin(X).
-spec sinh(float()) -> float().
sinh(X) ->
math:sinh(X).
-spec tan(float()) -> float().
tan(X) ->
math:tan(X).
-spec tanh(float()) -> float().
tanh(X) ->
math:tanh(X).
-spec to_degrees(float()) -> float().
to_degrees(X) ->
case pi() of
0.0 -> 0.0;
Gleam@denominator -> (X * 180.0) / Gleam@denominator
end.
-spec to_radians(float()) -> float().
to_radians(X) ->
(X * pi()) / 180.0.
-spec beta(float(), float()) -> float().
beta(X, Y) ->
case gamma(X + Y) of
0.0 -> 0.0;
Gleam@denominator -> (gamma(X) * gamma(Y)) / Gleam@denominator
end.
-spec erf(float()) -> float().
erf(X) ->
[A1, A2, A3, A4, A5] = [0.254829592,
-0.284496736,
1.421413741,
-1.453152027,
1.061405429],
P = 0.3275911,
Sign = case X < 0.0 of
true ->
-1.0;
false ->
1.0
end,
X@1 = gleam@float:absolute_value(X),
T = case (1.0 + (P * X@1)) of
0.0 -> 0.0;
Gleam@denominator -> 1.0 / Gleam@denominator
end,
Y = 1.0 - ((((((((((A5 * T) + A4) * T) + A3) * T) + A2) * T) + A1) * T) * exp(
(-1.0
* X@1)
* X@1
)),
Sign * Y.
-spec gamma(float()) -> float().
gamma(X) ->
gamma_lanczos(X).
-spec gamma_lanczos(float()) -> float().
gamma_lanczos(X) ->
case X < 0.5 of
true ->
case (sin(pi() * X) * gamma_lanczos(1.0 - X)) of
0.0 -> 0.0;
Gleam@denominator -> pi() / Gleam@denominator
end;
false ->
Z = X - 1.0,
X@1 = gleam@list:index_fold(
[0.99999999999980993,
676.5203681218851,
-1259.1392167224028,
771.32342877765313,
-176.61502916214059,
12.507343278686905,
-0.13857109526572012,
0.0000099843695780195716,
0.00000015056327351493116],
0.0,
fun(Acc, V, Index) -> case Index > 0 of
true ->
Acc + (case (Z + gleam@int:to_float(Index)) of
0.0 -> 0.0;
Gleam@denominator@1 -> V / Gleam@denominator@1
end);
false ->
V
end end
),
T = (Z + 7.0) + 0.5,
{ok, V1@1} = case pow(2.0 * pi(), 0.5) of
{ok, V1} -> {ok, V1};
_try ->
erlang:error(#{gleam_error => assert,
message => <<"Assertion pattern match failed"/utf8>>,
value => _try,
module => <<"gleam_stats/math"/utf8>>,
function => <<"gamma_lanczos"/utf8>>,
line => 1329})
end,
{ok, V2@1} = case pow(T, Z + 0.5) of
{ok, V2} -> {ok, V2};
_try@1 ->
erlang:error(#{gleam_error => assert,
message => <<"Assertion pattern match failed"/utf8>>,
value => _try@1,
module => <<"gleam_stats/math"/utf8>>,
function => <<"gamma_lanczos"/utf8>>,
line => 1330})
end,
((V1@1 * V2@1) * exp(-1.0 * T)) * X@1
end.
-spec gammainc(float(), float()) -> {ok, float()} | {error, binary()}.
gammainc(A, X) ->
case (A > 0.0) andalso (X >= 0.0) of
true ->
{ok, V@1} = case pow(X, A) of
{ok, V} -> {ok, V};
_try ->
erlang:error(#{gleam_error => assert,
message => <<"Assertion pattern match failed"/utf8>>,
value => _try,
module => <<"gleam_stats/math"/utf8>>,
function => <<"gammainc"/utf8>>,
line => 1356})
end,
_pipe = (V@1 * exp(-1.0 * X)) * gammainc_sum(A, X, case A of
0.0 -> 0.0;
Gleam@denominator -> 1.0 / Gleam@denominator
end, 0.0, 1.0),
{ok, _pipe};
false ->
_pipe@1 = <<"Invlaid input argument: a <= 0 or x < 0. Valid input is a > 0 and x >= 0."/utf8>>,
{error, _pipe@1}
end.
-spec gammainc_sum(float(), float(), float(), float(), float()) -> float().
gammainc_sum(A, X, T, S, N) ->
case T of
0.0 ->
S;
_@1 ->
Ns = S + T,
Nt = T * (case (A + N) of
0.0 -> 0.0;
Gleam@denominator -> X / Gleam@denominator
end),
gammainc_sum(A, X, Nt, Ns, N + 1.0)
end.
-spec round(float(), integer()) -> float().
round(X, Precision) ->
{ok, P@1} = case pow(10.0, gleam@int:to_float(Precision)) of
{ok, P} -> {ok, P};
_try ->
erlang:error(#{gleam_error => assert,
message => <<"Assertion pattern match failed"/utf8>>,
value => _try,
module => <<"gleam_stats/math"/utf8>>,
function => <<"round"/utf8>>,
line => 1414})
end,
case P@1 of
0.0 -> 0.0;
Gleam@denominator -> gleam@int:to_float(gleam@float:round(X * P@1)) / Gleam@denominator
end.
-spec combination(integer(), integer()) -> {ok, integer()} | {error, binary()}.
combination(N, K) ->
case N < 0 of
true ->
_pipe = <<"Invalid input argument: n < 0. Valid input is n > 0."/utf8>>,
{error, _pipe};
false ->
case (K < 0) orelse (K > N) of
true ->
_pipe@1 = 0,
{ok, _pipe@1};
false ->
case (K =:= 0) orelse (K =:= N) of
true ->
_pipe@2 = 1,
{ok, _pipe@2};
false ->
Min = case K < (N - K) of
true ->
K;
false ->
N - K
end,
_pipe@3 = gleam@list:range(1, Min + 1),
_pipe@4 = gleam@list:fold(
_pipe@3,
1,
fun(Acc, X) -> case X of
0 -> 0;
Gleam@denominator -> (Acc * ((N + 1) - X)) div Gleam@denominator
end end
),
{ok, _pipe@4}
end
end
end.
-spec factorial(integer()) -> {ok, integer()} | {error, binary()}.
factorial(N) ->
case N < 0 of
true ->
_pipe = <<"Invalid input argument: n < 0. Valid input is n > 0."/utf8>>,
{error, _pipe};
false ->
case N of
0 ->
_pipe@1 = 1,
{ok, _pipe@1};
1 ->
_pipe@2 = 1,
{ok, _pipe@2};
_@1 ->
_pipe@3 = gleam@list:range(1, N + 1),
_pipe@4 = gleam@list:fold(
_pipe@3,
1,
fun(Acc, X) -> Acc * X end
),
{ok, _pipe@4}
end
end.
-spec permutation(integer(), integer()) -> {ok, integer()} | {error, binary()}.
permutation(N, K) ->
case N < 0 of
true ->
_pipe = <<"Invalid input argument: n < 0. Valid input is n > 0."/utf8>>,
{error, _pipe};
false ->
case (K < 0) orelse (K > N) of
true ->
_pipe@1 = 0,
{ok, _pipe@1};
false ->
case K =:= N of
true ->
_pipe@2 = 1,
{ok, _pipe@2};
false ->
{ok, V1@1} = case factorial(N) of
{ok, V1} -> {ok, V1};
_try ->
erlang:error(#{gleam_error => assert,
message => <<"Assertion pattern match failed"/utf8>>,
value => _try,
module => <<"gleam_stats/math"/utf8>>,
function => <<"permutation"/utf8>>,
line => 1615})
end,
{ok, V2@1} = case factorial(N - K) of
{ok, V2} -> {ok, V2};
_try@1 ->
erlang:error(#{gleam_error => assert,
message => <<"Assertion pattern match failed"/utf8>>,
value => _try@1,
module => <<"gleam_stats/math"/utf8>>,
function => <<"permutation"/utf8>>,
line => 1616})
end,
_pipe@3 = case V2@1 of
0 -> 0;
Gleam@denominator -> V1@1 div Gleam@denominator
end,
{ok, _pipe@3}
end
end
end.
-spec pi() -> float().
pi() ->
math:pi().
-spec tau() -> float().
tau() ->
2.0 * pi().