Current section

Files

Jump to
themis src themis@number.erl
Raw

src/themis@number.erl

-module(themis@number).
-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch]).
-define(FILEPATH, "src/themis/number.gleam").
-export([integer/1, decimal/1, positive_infinity/0, negative_infinity/0, not_a_number/0, compare/2, unsafe_compare/2, add/2, print/1]).
-export_type([comparison_error/0, number_/0]).
-if(?OTP_RELEASE >= 27).
-define(MODULEDOC(Str), -moduledoc(Str)).
-define(DOC(Str), -doc(Str)).
-else.
-define(MODULEDOC(Str), -compile([])).
-define(DOC(Str), -compile([])).
-endif.
-type comparison_error() :: na_n_value.
-type number_() :: pos_inf | neg_inf | na_n | {dec, float()} | {int, integer()}.
-file("src/themis/number.gleam", 21).
?DOC(" Creates a Number representing an integer value.\n").
-spec integer(integer()) -> number_().
integer(Value) ->
{int, Value}.
-file("src/themis/number.gleam", 26).
?DOC(" Creates a Number representing a decimal value.\n").
-spec decimal(float()) -> number_().
decimal(Value) ->
{dec, Value}.
-file("src/themis/number.gleam", 31).
?DOC(" Creates a Number representing positive infinity.\n").
-spec positive_infinity() -> number_().
positive_infinity() ->
pos_inf.
-file("src/themis/number.gleam", 36).
?DOC(" Creates a Number representing negative infinity.\n").
-spec negative_infinity() -> number_().
negative_infinity() ->
neg_inf.
-file("src/themis/number.gleam", 41).
?DOC(" Creates a Number representing NaN (Not a Number).\n").
-spec not_a_number() -> number_().
not_a_number() ->
na_n.
-file("src/themis/number.gleam", 47).
?DOC(
" Compare two numbers (see gleam_stdlib/order)\n"
" Will return an error if either value is NaN\n"
).
-spec compare(number_(), number_()) -> {ok, gleam@order:order()} |
{error, comparison_error()}.
compare(Val1, Val2) ->
case {Val1, Val2} of
{V1, V2} when V1 =:= V2 ->
{ok, eq};
{{int, V1@1}, {int, V2@1}} ->
{ok, gleam@int:compare(V1@1, V2@1)};
{{dec, V1@2}, {dec, V2@2}} ->
{ok, gleam@float:compare(V1@2, V2@2)};
{pos_inf, _} ->
{ok, gt};
{neg_inf, _} ->
{ok, lt};
{_, pos_inf} ->
{ok, lt};
{_, neg_inf} ->
{ok, gt};
{{dec, D}, {int, I}} ->
{ok, gleam@float:compare(D, erlang:float(I))};
{{int, I@1}, {dec, D@1}} ->
{ok, gleam@float:compare(erlang:float(I@1), D@1)};
{na_n, _} ->
{error, na_n_value};
{_, na_n} ->
{error, na_n_value}
end.
-file("src/themis/number.gleam", 67).
?DOC(
" Compare two numbers (see gleam_stdlib/order)\n"
" Will panic if either value is NaN\n"
).
-spec unsafe_compare(number_(), number_()) -> gleam@order:order().
unsafe_compare(Val1, Val2) ->
case compare(Val1, Val2) of
{error, _} ->
erlang:error(#{gleam_error => panic,
message => <<"cannot compare NaN"/utf8>>,
file => <<?FILEPATH/utf8>>,
module => <<"themis/number"/utf8>>,
function => <<"unsafe_compare"/utf8>>,
line => 69});
{ok, R} ->
R
end.
-file("src/themis/number.gleam", 77).
?DOC(
" Add two numbers.\n"
" Any `NaN` input value will always return `NaN`.\n"
" `PosInf` + `NegInf` = `NaN`\n"
).
-spec add(number_(), number_()) -> number_().
add(Val1, Val2) ->
case {Val1, Val2} of
{na_n, _} ->
na_n;
{_, na_n} ->
na_n;
{{int, First}, {int, Second}} ->
{int, First + Second};
{{dec, First@1}, {dec, Second@1}} ->
{dec, gleam@float:add(First@1, Second@1)};
{{dec, Dec}, {int, Int}} ->
{dec, gleam@float:add(erlang:float(Int), Dec)};
{{int, Int}, {dec, Dec}} ->
{dec, gleam@float:add(erlang:float(Int), Dec)};
{pos_inf, neg_inf} ->
na_n;
{neg_inf, pos_inf} ->
na_n;
{pos_inf, _} ->
pos_inf;
{_, pos_inf} ->
pos_inf;
{neg_inf, _} ->
neg_inf;
{_, neg_inf} ->
neg_inf
end.
-file("src/themis/number.gleam", 91).
?DOC(" Prometheus-scrapable representation of a number\n").
-spec print(number_()) -> binary().
print(Number) ->
case Number of
{dec, Val} ->
gleam_stdlib:float_to_string(Val);
{int, Val@1} ->
erlang:integer_to_binary(Val@1);
na_n ->
<<"NaN"/utf8>>;
neg_inf ->
<<"-Inf"/utf8>>;
pos_inf ->
<<"+Inf"/utf8>>
end.