Packages

A rational number library for gleam.

Current section

Files

Jump to
ratioed src ratioed.erl
Raw

src/ratioed.erl

-module(ratioed).
-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch]).
-export([from_i/1, to_i/1, to_f/1, to_string/1, compare/2, from_i2/2, add/2, sub/2, mul/2, 'div'/2, from_f_epsilon/2, from_f/1]).
-export_type([ratio/0]).
-opaque ratio() :: {ratio, integer(), integer()}.
-file("/home/julian/projects/ratioed/src/ratioed.gleam", 14).
-spec from_i(integer()) -> ratio().
from_i(N) ->
{ratio, N, 1}.
-file("/home/julian/projects/ratioed/src/ratioed.gleam", 38).
-spec to_i(ratio()) -> integer().
to_i(A) ->
case erlang:element(3, A) of
0 -> 0;
Gleam@denominator -> erlang:element(2, A) div Gleam@denominator
end.
-file("/home/julian/projects/ratioed/src/ratioed.gleam", 43).
-spec to_f(ratio()) -> float().
to_f(Ratio) ->
case gleam@int:to_float(erlang:element(3, Ratio)) of
+0.0 -> +0.0;
-0.0 -> -0.0;
Gleam@denominator -> gleam@int:to_float(erlang:element(2, Ratio)) / Gleam@denominator
end.
-file("/home/julian/projects/ratioed/src/ratioed.gleam", 48).
-spec to_string(ratio()) -> binary().
to_string(Ratio) ->
<<<<(gleam@int:to_string(erlang:element(2, Ratio)))/binary, "/"/utf8>>/binary,
(gleam@int:to_string(erlang:element(3, Ratio)))/binary>>.
-file("/home/julian/projects/ratioed/src/ratioed.gleam", 53).
-spec compare(ratio(), ratio()) -> gleam@order:order().
compare(A, B) ->
gleam@int:compare(
erlang:element(2, A) * erlang:element(3, B),
erlang:element(3, A) * erlang:element(2, B)
).
-file("/home/julian/projects/ratioed/src/ratioed.gleam", 82).
-spec abs(integer()) -> integer().
abs(X) ->
case X < 0 of
true ->
- X;
false ->
X
end.
-file("/home/julian/projects/ratioed/src/ratioed.gleam", 93).
-spec do_gcd(integer(), integer()) -> integer().
do_gcd(X, Y) ->
case X =:= 0 of
true ->
Y;
false ->
_assert_subject = gleam@int:modulo(Y, X),
{ok, Z} = case _assert_subject of
{ok, _} -> _assert_subject;
_assert_fail ->
erlang:error(#{gleam_error => let_assert,
message => <<"Pattern match failed, no pattern matched the value."/utf8>>,
value => _assert_fail,
module => <<"ratioed"/utf8>>,
function => <<"do_gcd"/utf8>>,
line => 97})
end,
do_gcd(Z, X)
end.
-file("/home/julian/projects/ratioed/src/ratioed.gleam", 89).
-spec gcd(integer(), integer()) -> integer().
gcd(X, Y) ->
do_gcd(abs(X), abs(Y)).
-file("/home/julian/projects/ratioed/src/ratioed.gleam", 77).
-spec simplify(integer(), integer()) -> ratio().
simplify(N, D) ->
Gcd = gcd(N, D),
{ratio, case Gcd of
0 -> 0;
Gleam@denominator -> N div Gleam@denominator
end, case Gcd of
0 -> 0;
Gleam@denominator@1 -> D div Gleam@denominator@1
end}.
-file("/home/julian/projects/ratioed/src/ratioed.gleam", 19).
-spec from_i2(integer(), integer()) -> ratio().
from_i2(N, D) ->
case {N, D} of
{_, 0} ->
{ratio, 0, 1};
{0, _} ->
{ratio, 0, 1};
{_, _} when D < 0 ->
simplify(- N, - D);
{_, _} ->
simplify(N, D)
end.
-file("/home/julian/projects/ratioed/src/ratioed.gleam", 58).
-spec add(ratio(), ratio()) -> ratio().
add(A, B) ->
from_i2(
(erlang:element(2, A) * erlang:element(3, B)) + (erlang:element(3, A) * erlang:element(
2,
B
)),
erlang:element(3, A) * erlang:element(3, B)
).
-file("/home/julian/projects/ratioed/src/ratioed.gleam", 63).
-spec sub(ratio(), ratio()) -> ratio().
sub(A, B) ->
from_i2(
(erlang:element(2, A) * erlang:element(3, B)) - (erlang:element(3, A) * erlang:element(
2,
B
)),
erlang:element(3, A) * erlang:element(3, B)
).
-file("/home/julian/projects/ratioed/src/ratioed.gleam", 68).
-spec mul(ratio(), ratio()) -> ratio().
mul(A, B) ->
from_i2(
erlang:element(2, A) * erlang:element(2, B),
erlang:element(3, A) * erlang:element(3, B)
).
-file("/home/julian/projects/ratioed/src/ratioed.gleam", 73).
-spec 'div'(ratio(), ratio()) -> ratio().
'div'(A, B) ->
from_i2(
erlang:element(2, A) * erlang:element(3, B),
erlang:element(3, A) * erlang:element(2, B)
).
-file("/home/julian/projects/ratioed/src/ratioed.gleam", 109).
-spec continued_fraction(
any(),
integer(),
integer(),
integer(),
integer(),
float(),
float(),
float(),
float(),
float(),
float(),
float()
) -> ratio().
continued_fraction(Tol, P, Q, Pp, Qq, X, Y, R, A, Nt, T, Tt) ->
case R > Nt of
true ->
Np = (gleam@float:truncate(A) * P) + Pp,
Nq = (gleam@float:truncate(A) * Q) + Qq,
Pp@1 = P,
P@1 = Np,
Qq@1 = Q,
Q@1 = Nq,
X@1 = Y,
Y@1 = R,
R@1 = math:fmod(X@1, Y@1),
A@1 = gleam@float:floor(case Y@1 of
+0.0 -> +0.0;
-0.0 -> -0.0;
Gleam@denominator -> X@1 / Gleam@denominator
end),
Tt@1 = T,
T@1 = Nt,
Nt@1 = (A@1 * T@1) + Tt@1,
continued_fraction(
Tol,
P@1,
Q@1,
Pp@1,
Qq@1,
X@1,
Y@1,
R@1,
A@1,
Nt@1,
T@1,
Tt@1
);
false ->
I = gleam@float:truncate(gleam@float:ceiling(case (Y + T) of
+0.0 -> +0.0;
-0.0 -> -0.0;
Gleam@denominator@1 -> (X - Tt) / Gleam@denominator@1
end)),
from_i2((I * P) + Pp, (I * Q) + Qq)
end.
-file("/home/julian/projects/ratioed/src/ratioed.gleam", 103).
-spec approx_ratio(float(), float()) -> ratio().
approx_ratio(Tol, X) ->
A = gleam@float:floor(X),
R = X - A,
continued_fraction(Tol, 1, 0, 0, 1, X, 1.0, R, A, Tol, +0.0, Tol).
-file("/home/julian/projects/ratioed/src/ratioed.gleam", 33).
-spec from_f_epsilon(float(), float()) -> ratio().
from_f_epsilon(F, E) ->
approx_ratio(E, F).
-file("/home/julian/projects/ratioed/src/ratioed.gleam", 28).
-spec from_f(float()) -> ratio().
from_f(F) ->
approx_ratio(4.440892098500626e-16, F).