-module(glib@fraction). -compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch]). -export([compare/2, equals/2, to_float/1, to_int/1, numerator/1, denominator/1, proper_numerator/1, proper_whole/1, to_string/1, to_proper_string/1, negate/1, abs/1, new/2, new2/3, inverse/1, reduce/1, multiply/2, divide/2, power/2, add/2, sub/2, from_float/1, from_string/1]). -export_type([fraction/0, fraction_error/0, internal_fraction/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. ?MODULEDOC( " General Fraction functions\n" " Fraction type allow for accurate storage and manipulation\n" " of fractions\n" " \n" " There is a current limitation of 9007199254740991 for the \n" " numerator and denominator. This is because this is the largest\n" " 'safe' integer in Javascript.\n" ). -type fraction() :: {fraction, integer(), integer()}. -type fraction_error() :: {zero_denominator, binary()} | {overflow, binary()} | {too_large, binary()} | {conversion_error, binary()} | {divide_by_zero, binary()}. -type internal_fraction() :: {internal_fraction, fraction(), fraction(), integer(), float(), float(), float(), float()}. -file("src/glib/fraction.gleam", 202). -spec compare(fraction(), fraction()) -> gleam@order:order(). compare(Fr1, Fr2) -> gleam@bool:guard( Fr1 =:= Fr2, eq, fun() -> gleam@int:compare( erlang:element(2, Fr1) * erlang:element(3, Fr2), erlang:element(3, Fr1) * erlang:element(2, Fr2) ) end ). -file("src/glib/fraction.gleam", 207). -spec equals(fraction(), fraction()) -> boolean(). equals(Fr1, Fr2) -> compare(Fr1, Fr2) =:= eq. -file("src/glib/fraction.gleam", 211). -spec to_float(fraction()) -> float(). to_float(Fr1) -> case erlang:float(erlang:element(3, Fr1)) of +0.0 -> +0.0; -0.0 -> -0.0; Gleam@denominator -> erlang:float(erlang:element(2, Fr1)) / Gleam@denominator end. -file("src/glib/fraction.gleam", 215). -spec to_int(fraction()) -> integer(). to_int(Fr1) -> case erlang:element(3, Fr1) of 0 -> 0; Gleam@denominator -> erlang:element(2, Fr1) div Gleam@denominator end. -file("src/glib/fraction.gleam", 219). -spec numerator(fraction()) -> integer(). numerator(Fr1) -> erlang:element(2, Fr1). -file("src/glib/fraction.gleam", 223). -spec denominator(fraction()) -> integer(). denominator(Fr1) -> erlang:element(3, Fr1). -file("src/glib/fraction.gleam", 227). -spec proper_numerator(fraction()) -> integer(). proper_numerator(Fr1) -> gleam@int:absolute_value(case erlang:element(3, Fr1) of 0 -> 0; Gleam@denominator -> erlang:element(2, Fr1) rem Gleam@denominator end). -file("src/glib/fraction.gleam", 231). -spec proper_whole(fraction()) -> integer(). proper_whole(Fr1) -> to_int(Fr1). -file("src/glib/fraction.gleam", 312). -spec to_string(fraction()) -> binary(). to_string(Fr1) -> <<<<(erlang:integer_to_binary(erlang:element(2, Fr1)))/binary, "/"/utf8>>/binary, (erlang:integer_to_binary(erlang:element(3, Fr1)))/binary>>. -file("src/glib/fraction.gleam", 316). -spec to_proper_string(fraction()) -> binary(). to_proper_string(Fr1) -> gleam@bool:guard( erlang:element(2, Fr1) =:= 0, <<"0"/utf8>>, fun() -> gleam@bool:guard( erlang:element(2, Fr1) =:= erlang:element(3, Fr1), <<"1"/utf8>>, fun() -> gleam@bool:guard( erlang:element(2, Fr1) =:= - erlang:element(3, Fr1), <<"-1"/utf8>>, fun() -> case - gleam@int:absolute_value( erlang:element(2, Fr1) ) < - erlang:element(3, Fr1) of true -> Prop_num = proper_numerator(Fr1), case Prop_num =:= 0 of true -> erlang:integer_to_binary( proper_whole(Fr1) ); false -> <<<<<<<<(erlang:integer_to_binary( proper_whole( Fr1 ) ))/binary, " "/utf8>>/binary, (erlang:integer_to_binary( Prop_num ))/binary>>/binary, "/"/utf8>>/binary, (erlang:integer_to_binary( erlang:element(3, Fr1) ))/binary>> end; false -> to_string(Fr1) end end ) end ) end ). -file("src/glib/fraction.gleam", 609). -spec divide_while_even(integer()) -> integer(). divide_while_even(T) -> case gleam@int:is_even(T) of true -> divide_while_even(T div 2); false -> T end. -file("src/glib/fraction.gleam", 593). -spec reduce_t(integer(), {integer(), integer()}) -> integer(). reduce_t(T, Uv) -> {U, V} = Uv, T@1 = divide_while_even(T), {U@1, V@1} = case gleam@int:compare(T@1, 0) of gt -> {- T@1, V}; _ -> {U, T@1} end, T@2 = (V@1 - U@1) div 2, case T@2 =:= 0 of true -> U@1; false -> reduce_t(T@2, {U@1, V@1}) end. -file("src/glib/fraction.gleam", 178). -spec negate(fraction()) -> {ok, fraction()} | {error, fraction_error()}. negate(Fr) -> case - erlang:element(2, Fr) > 9007199254740991 of true -> {error, {overflow, <<"Cannot negate "/utf8, (erlang:integer_to_binary(erlang:element(2, Fr)))/binary>>}}; false -> {ok, {fraction, - erlang:element(2, Fr), erlang:element(3, Fr)}} end. -file("src/glib/fraction.gleam", 187). -spec abs(fraction()) -> {ok, fraction()} | {error, fraction_error()}. abs(Fr) -> case erlang:element(2, Fr) >= 0 of true -> {ok, Fr}; false -> negate(Fr) end. -file("src/glib/fraction.gleam", 426). -spec mul_pos(integer(), integer()) -> {ok, integer()} | {error, fraction_error()}. mul_pos(X, Y) -> M = X * Y, case M > 9007199254740991 of true -> {error, {overflow, <<<<<<"multiplying "/utf8, (erlang:integer_to_binary(X))/binary>>/binary, " and "/utf8>>/binary, (erlang:integer_to_binary(Y))/binary>>}}; false -> {ok, M} end. -file("src/glib/fraction.gleam", 616). -spec internal_calc(float(), internal_fraction()) -> internal_fraction(). internal_calc(Value, Fr) -> A2 = erlang:trunc(case erlang:element(6, Fr) =:= +0.0 of true -> erlang:float(9007199254740991); false -> case erlang:element(6, Fr) of +0.0 -> +0.0; -0.0 -> -0.0; Gleam@denominator -> erlang:element(5, Fr) / Gleam@denominator end end), X2 = erlang:element(6, Fr), Y2 = erlang:element(5, Fr) - (erlang:float(A2) * erlang:element(6, Fr)), Fr2 = {fraction, (erlang:element(4, Fr) * erlang:element(2, erlang:element(3, Fr))) + erlang:element( 2, erlang:element(2, Fr) ), (erlang:element(4, Fr) * erlang:element(3, erlang:element(3, Fr))) + erlang:element( 3, erlang:element(2, Fr) )}, Fraction = case erlang:float(erlang:element(3, Fr2)) of +0.0 -> +0.0; -0.0 -> -0.0; Gleam@denominator@1 -> erlang:float(erlang:element(2, Fr2)) / Gleam@denominator@1 end, Delta2 = gleam@float:absolute_value(Value - Fraction), {internal_fraction, erlang:element(3, Fr), Fr2, A2, X2, Y2, erlang:element(8, Fr), Delta2}. -file("src/glib/fraction.gleam", 71). -spec new(integer(), integer()) -> {ok, fraction()} | {error, fraction_error()}. new(Numerator, Denominator) -> gleam@bool:guard( Denominator =:= 0, {error, {zero_denominator, <<"Denominator is zero"/utf8>>}}, fun() -> case Denominator < 0 of true -> gleam@bool:guard( (Numerator =:= -9007199254740991) orelse (Denominator =:= -9007199254740991), {error, {overflow, <<"Denominator or Numerator is -9007199254740991"/utf8>>}}, fun() -> {ok, {fraction, - Numerator, - Denominator}} end ); false -> {ok, {fraction, Numerator, Denominator}} end end ). -file("src/glib/fraction.gleam", 90). -spec new2(integer(), integer(), integer()) -> {ok, fraction()} | {error, fraction_error()}. new2(Whole, Numerator, Denominator) -> gleam@bool:guard( Denominator =:= 0, {error, {zero_denominator, <<"Denominator is zero"/utf8>>}}, fun() -> gleam@bool:guard( Denominator < 0, {error, {zero_denominator, <<"Denominator is less than zero"/utf8>>}}, fun() -> gleam@bool:guard( Numerator < 0, {error, {zero_denominator, <<"Numerator is less than zero"/utf8>>}}, fun() -> Numerator@1 = case Whole < 0 of true -> (Whole * Denominator) - Numerator; false -> (Whole * Denominator) + Numerator end, gleam@bool:guard( (Numerator@1 < -9007199254740991) orelse (Numerator@1 > 9007199254740991), {error, {overflow, <<"Numerator overflows"/utf8>>}}, fun() -> {ok, {fraction, Numerator@1, Denominator}} end ) end ) end ) end ). -file("src/glib/fraction.gleam", 235). -spec inverse(fraction()) -> {ok, fraction()} | {error, fraction_error()}. inverse(Fr1) -> gleam@bool:guard( erlang:element(2, Fr1) =:= 0, {error, {zero_denominator, <<"Inverse"/utf8>>}}, fun() -> gleam@bool:guard( erlang:element(2, Fr1) =:= -9007199254740991, {error, {overflow, <<"Inverse"/utf8>>}}, fun() -> case erlang:element(2, Fr1) < 0 of true -> {ok, {fraction, - erlang:element(3, Fr1), - erlang:element(2, Fr1)}}; false -> {ok, {fraction, erlang:element(3, Fr1), erlang:element(2, Fr1)}} end end ) end ). -file("src/glib/fraction.gleam", 393). -spec mul_check(integer(), integer()) -> {ok, integer()} | {error, fraction_error()}. mul_check(X, Y) -> M = X * Y, case (M < -9007199254740991) orelse (M > 9007199254740991) of true -> {error, {overflow, <<<<<<"multiplying "/utf8, (erlang:integer_to_binary(X))/binary>>/binary, " and "/utf8>>/binary, (erlang:integer_to_binary(Y))/binary>>}}; false -> {ok, M} end. -file("src/glib/fraction.gleam", 404). -spec add_check(integer(), integer()) -> {ok, integer()} | {error, fraction_error()}. add_check(X, Y) -> A = X + Y, case (A < -9007199254740991) orelse (A > 9007199254740991) of true -> {error, {overflow, <<<<<<"adding "/utf8, (erlang:integer_to_binary(X))/binary>>/binary, " and "/utf8>>/binary, (erlang:integer_to_binary(Y))/binary>>}}; false -> {ok, A} end. -file("src/glib/fraction.gleam", 415). -spec sub_check(integer(), integer()) -> {ok, integer()} | {error, fraction_error()}. sub_check(X, Y) -> S = X - Y, case (S < -9007199254740991) orelse (S > 9007199254740991) of true -> {error, {overflow, <<<<<<"subtracting "/utf8, (erlang:integer_to_binary(Y))/binary>>/binary, " from "/utf8>>/binary, (erlang:integer_to_binary(X))/binary>>}}; false -> {ok, S} end. -file("src/glib/fraction.gleam", 437). -spec parse_with_whole(binary(), binary()) -> {ok, fraction()} | {error, fraction_error()}. parse_with_whole(Whole, Fraction) -> gleam@result:'try'( begin _pipe = gleam_stdlib:parse_int(Whole), gleam@result:replace_error(_pipe, {conversion_error, Whole}) end, fun(Whole@1) -> case gleam@string:split(Fraction, <<"/"/utf8>>) of [Numer, Denom] -> gleam@result:'try'( begin _pipe@1 = gleam_stdlib:parse_int(Numer), gleam@result:replace_error( _pipe@1, {conversion_error, Numer} ) end, fun(Numer@1) -> gleam@result:'try'( begin _pipe@2 = gleam_stdlib:parse_int(Denom), gleam@result:replace_error( _pipe@2, {conversion_error, Denom} ) end, fun(Denom@1) -> new2(Whole@1, Numer@1, Denom@1) end ) end ); _ -> {error, {conversion_error, Fraction}} end end ). -file("src/glib/fraction.gleam", 460). -spec parse_fraction(binary()) -> {ok, fraction()} | {error, fraction_error()}. parse_fraction(Fraction) -> case gleam@string:split(Fraction, <<"/"/utf8>>) of [Numer, Denom] -> gleam@result:'try'( begin _pipe = gleam_stdlib:parse_int(Numer), gleam@result:replace_error(_pipe, {conversion_error, Numer}) end, fun(Numer@1) -> gleam@result:'try'( begin _pipe@1 = gleam_stdlib:parse_int(Denom), gleam@result:replace_error( _pipe@1, {conversion_error, Denom} ) end, fun(Denom@1) -> new(Numer@1, Denom@1) end ) end ); _ -> {error, {conversion_error, Fraction}} end. -file("src/glib/fraction.gleam", 541). -spec gcd(integer(), integer()) -> {ok, integer()} | {error, fraction_error()}. gcd(U, V) -> case (U =:= 0) orelse (V =:= 0) of true -> case (U =:= -9007199254740991) orelse (V =:= -9007199254740991) of true -> {error, {overflow, <<"gcd"/utf8>>}}; false -> {ok, gleam@int:absolute_value(U) + gleam@int:absolute_value( V )} end; false -> case (gleam@int:absolute_value(U) =:= 1) orelse (gleam@int:absolute_value( V ) =:= 1) of true -> {ok, 1}; false -> U@1 = case U > 0 of true -> - U; false -> U end, V@1 = case V > 0 of true -> - V; false -> V end, {U@3, V@3, K@1} = begin _pipe = gleam@list:range(0, 31), gleam@list:fold_until( _pipe, {U@1, V@1, 0}, fun(Vals, K) -> {U@2, V@2, _} = Vals, case K =:= 31 of true -> {stop, {-1, -1, -1}}; false -> case gleam@int:is_odd(U@2) orelse gleam@int:is_odd( V@2 ) of false -> {continue, {erlang:element(1, Vals) div 2, erlang:element(2, Vals) div 2, K}}; true -> {stop, {U@2, V@2, K}} end end end ) end, gleam@bool:guard( K@1 =:= -1, {error, {overflow, <<"gcd iteration"/utf8>>}}, fun() -> T = case gleam@int:is_odd(U@3) of true -> V@3; false -> - U@3 div 2 end, U@4 = reduce_t(T, {U@3, V@3}), {ok, - U@4 * erlang:'bsl'(1, K@1)} end ) end end. -file("src/glib/fraction.gleam", 152). -spec reduce(fraction()) -> {ok, fraction()} | {error, fraction_error()}. reduce(Fr) -> gleam@bool:guard( erlang:element(3, Fr) =:= 0, {error, {zero_denominator, <<"Denominator is zero"/utf8>>}}, fun() -> gleam@bool:guard( erlang:element(2, Fr) =:= 0, {ok, {fraction, 0, 1}}, fun() -> Fr@1 = case {erlang:element(3, Fr) =:= -9007199254740991, gleam@int:is_even(erlang:element(2, Fr))} of {true, true} -> {fraction, erlang:element(2, Fr) div 2, erlang:element(3, Fr) div 2}; {_, _} -> Fr end, gleam@result:'try'(case erlang:element(3, Fr@1) < 0 of true -> case {erlang:element(2, Fr@1) =:= -9007199254740991, erlang:element(3, Fr@1) =:= -9007199254740991} of {false, false} -> {ok, {fraction, - erlang:element(2, Fr@1), - erlang:element(3, Fr@1)}}; {_, _} -> {error, {overflow, <<"Denominator or Numerator is -9007199254740991"/utf8>>}} end; false -> {ok, Fr@1} end, fun(Fr@2) -> gleam@result:'try'( gcd( erlang:element(2, Fr@2), erlang:element(3, Fr@2) ), fun(Gcd) -> {ok, {fraction, case Gcd of 0 -> 0; Gleam@denominator -> erlang:element( 2, Fr@2 ) div Gleam@denominator end, case Gcd of 0 -> 0; Gleam@denominator@1 -> erlang:element( 3, Fr@2 ) div Gleam@denominator@1 end}} end ) end) end ) end ). -file("src/glib/fraction.gleam", 251). -spec multiply(fraction(), fraction()) -> {ok, fraction()} | {error, fraction_error()}. multiply(Fr1, Fr2) -> gleam@bool:guard( (erlang:element(2, Fr1) =:= 0) orelse (erlang:element(2, Fr2) =:= 0), {ok, {fraction, 0, 1}}, fun() -> gleam@result:'try'( gcd(erlang:element(2, Fr1), erlang:element(3, Fr2)), fun(Gcd1) -> gleam@result:'try'( gcd(erlang:element(2, Fr2), erlang:element(3, Fr1)), fun(Gcd2) -> gleam@result:'try'(mul_check(case Gcd1 of 0 -> 0; Gleam@denominator -> erlang:element( 2, Fr1 ) div Gleam@denominator end, case Gcd2 of 0 -> 0; Gleam@denominator@1 -> erlang:element( 2, Fr2 ) div Gleam@denominator@1 end), fun(Multnum) -> gleam@result:'try'(mul_pos(case Gcd2 of 0 -> 0; Gleam@denominator@2 -> erlang:element( 3, Fr1 ) div Gleam@denominator@2 end, case Gcd1 of 0 -> 0; Gleam@denominator@3 -> erlang:element( 3, Fr2 ) div Gleam@denominator@3 end), fun(Multden) -> reduce({fraction, Multnum, Multden}) end) end) end ) end ) end ). -file("src/glib/fraction.gleam", 270). -spec divide(fraction(), fraction()) -> {ok, fraction()} | {error, fraction_error()}. divide(Fr1, Fr2) -> gleam@bool:guard( erlang:element(2, Fr2) =:= 0, {error, {divide_by_zero, <<""/utf8>>}}, fun() -> gleam@result:'try'( inverse(Fr2), fun(Fr2_inv) -> multiply(Fr1, Fr2_inv) end ) end ). -file("src/glib/fraction.gleam", 277). -spec power(fraction(), integer()) -> {ok, fraction()} | {error, fraction_error()}. power(Fr1, Pow) -> gleam@bool:guard( Pow =:= 1, {ok, Fr1}, fun() -> gleam@bool:guard( Pow =:= 0, {ok, {fraction, 1, 1}}, fun() -> case Pow < 0 of true -> case Pow =:= -9007199254740991 of true -> gleam@result:'try'( inverse(Fr1), fun(Inv) -> gleam@result:'try'( power(Inv, 2), fun(Sq) -> Half_pow = Pow div 2, power(Sq, - Half_pow) end ) end ); false -> gleam@result:'try'( inverse(Fr1), fun(Inv@1) -> power(Inv@1, - Pow) end ) end; false -> gleam@result:'try'( multiply(Fr1, Fr1), fun(Fr2) -> gleam@result:'try'( power(Fr2, Pow div 2), fun(Half_pow@1) -> case gleam@int:is_even(Pow) of true -> {ok, Half_pow@1}; false -> multiply(Half_pow@1, Fr1) end end ) end ) end end ) end ). -file("src/glib/fraction.gleam", 342). -spec add_or_sub(fraction(), fraction(), boolean()) -> {ok, fraction()} | {error, fraction_error()}. add_or_sub(Fr1, Fr2, Add) -> gleam@bool:guard(erlang:element(2, Fr1) =:= 0, case Add of true -> {ok, Fr2}; false -> negate(Fr2) end, fun() -> gleam@bool:guard( erlang:element(2, Fr2) =:= 0, {ok, Fr1}, fun() -> gleam@result:'try'( gcd(erlang:element(3, Fr1), erlang:element(3, Fr2)), fun(Gcd1) -> gleam@bool:guard( Gcd1 =:= 1, begin gleam@result:'try'( mul_check( erlang:element(2, Fr1), erlang:element(3, Fr2) ), fun(Uvp) -> gleam@result:'try'( mul_check( erlang:element(2, Fr2), erlang:element(3, Fr1) ), fun(Upv) -> gleam@result:'try'( case Add of true -> add_check( Uvp, Upv ); false -> sub_check( Uvp, Upv ) end, fun(New_numerator) -> gleam@result:'try'( mul_pos( erlang:element( 3, Fr1 ), erlang:element( 3, Fr2 ) ), fun( New_denominator ) -> {ok, {fraction, New_numerator, New_denominator}} end ) end ) end ) end ) end, fun() -> Uvp@1 = erlang:element(2, Fr1) * (case Gcd1 of 0 -> 0; Gleam@denominator -> erlang:element( 3, Fr2 ) div Gleam@denominator end), Upv@1 = erlang:element(2, Fr2) * (case Gcd1 of 0 -> 0; Gleam@denominator@1 -> erlang:element( 3, Fr1 ) div Gleam@denominator@1 end), T = case Add of true -> Uvp@1 + Upv@1; false -> Uvp@1 - Upv@1 end, Tmod = case Gcd1 of 0 -> 0; Gleam@denominator@2 -> T rem Gleam@denominator@2 end, gleam@result:'try'(case Tmod =:= 0 of true -> {ok, Gcd1}; false -> gcd(Tmod, Gcd1) end, fun(Gcd2) -> W = case Gcd2 of 0 -> 0; Gleam@denominator@3 -> T div Gleam@denominator@3 end, case (W > 9007199254740991) orelse (W < -9007199254740991) of true -> {error, {overflow, <<(erlang:integer_to_binary( W ))/binary, " overflows"/utf8>>}}; false -> gleam@result:'try'( mul_pos(case Gcd1 of 0 -> 0; Gleam@denominator@4 -> erlang:element( 3, Fr1 ) div Gleam@denominator@4 end, case Gcd2 of 0 -> 0; Gleam@denominator@5 -> erlang:element( 3, Fr2 ) div Gleam@denominator@5 end), fun(New_denominator@1) -> {ok, {fraction, W, New_denominator@1}} end ) end end) end ) end ) end ) end). -file("src/glib/fraction.gleam", 194). -spec add(fraction(), fraction()) -> {ok, fraction()} | {error, fraction_error()}. add(Fr1, Fr2) -> add_or_sub(Fr1, Fr2, true). -file("src/glib/fraction.gleam", 198). -spec sub(fraction(), fraction()) -> {ok, fraction()} | {error, fraction_error()}. sub(Fr1, Fr2) -> add_or_sub(Fr1, Fr2, false). -file("src/glib/fraction.gleam", 488). -spec construct_fraction(integer(), integer(), float()) -> {ok, fraction()} | {error, fraction_error()}. construct_fraction(Sign, Whole, Value) -> A = {internal_fraction, {fraction, 0, 1}, {fraction, 1, 0}, 0, 1.0, Value, +0.0, 1.7976931348623157e308}, Fr@2 = begin _pipe = gleam@yielder:range(0, 24), gleam@yielder:fold_until( _pipe, A, fun(Fr, I) -> Fr@1 = internal_calc(Value, Fr), case ((erlang:element(7, Fr@1) > erlang:element(8, Fr@1)) andalso (erlang:element(3, erlang:element(3, Fr@1)) =< 10000)) andalso (erlang:element(3, erlang:element(3, Fr@1)) > 0) of false -> {stop, Fr@1}; true -> case I of 24 -> {stop, begin _record = A, {internal_fraction, {fraction, -1, -1}, erlang:element(3, _record), erlang:element(4, _record), erlang:element(5, _record), erlang:element(6, _record), erlang:element(7, _record), erlang:element(8, _record)} end}; _ -> {continue, Fr@1} end end end ) end, case Fr@2 of {internal_fraction, {fraction, -1, -1}, _, _, _, _, _, _} -> {error, {conversion_error, <<"Too many iterations"/utf8>>}}; _ -> _pipe@1 = {fraction, Sign * (erlang:element(2, erlang:element(2, Fr@2)) + (Whole * erlang:element( 3, erlang:element(2, Fr@2) ))), erlang:element(3, erlang:element(2, Fr@2))}, reduce(_pipe@1) end. -file("src/glib/fraction.gleam", 52). ?DOC( " Generates a Fraction from given float\n" " Returns error if number is larger than\n" " the max int value\n" " \n" " ## Examples\n" " \n" " ```gleam\n" " let fr = from_float(0.75)\n" " // -> Ok(Fraction(3, 4))\n" " ```\n" " \n" " ```gleam\n" " let fr = from_float(0.66666)\n" " // -> Ok(Fraction(2, 3))\n" " ```\n" ). -spec from_float(float()) -> {ok, fraction()} | {error, fraction_error()}. from_float(Num) -> Sign = case gleam@float:compare(Num, +0.0) of lt -> -1; _ -> 1 end, Num@1 = gleam@float:absolute_value(Num), gleam@bool:guard( Num@1 > erlang:float(9007199254740991), {error, {too_large, <<"> 9007199254740991"/utf8>>}}, fun() -> Whole = erlang:trunc(Num@1), Num@2 = Num@1 - erlang:float(Whole), construct_fraction(Sign, Whole, Num@2) end ). -file("src/glib/fraction.gleam", 125). -spec from_string(binary()) -> {ok, fraction()} | {error, fraction_error()}. from_string(Fraction) -> case gleam_stdlib:contains_string(Fraction, <<"."/utf8>>) of true -> case gleam_stdlib:parse_float(Fraction) of {ok, F} -> from_float(F); {error, _} -> {error, {conversion_error, Fraction}} end; false -> Parts = gleam@string:split(Fraction, <<" "/utf8>>), case Parts of [] -> {ok, {fraction, 0, 1}}; [Whole, Fraction@1] -> parse_with_whole(Whole, Fraction@1); [Fraction@2] -> case gleam_stdlib:parse_int(Fraction@2) of {ok, F@1} -> parse_with_whole( erlang:integer_to_binary(F@1), <<"0/1"/utf8>> ); {error, _} -> parse_fraction(Fraction@2) end; _ -> {error, {conversion_error, Fraction}} end end.