-module(glat). -compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch]). -export([from_int/1, from_float_check/1, to_int/1, to_int_floor/1, to_float/1, to_string/1, is_negative/1, is_positive/1, absolute_value/1, remainder/1, modulo/1, fraction/1, fraction_floor/1, floor/1, ceiling/1, negate/1, compare/2, round/1, add/2, subtract/2, multiply/2, max/2, min/2, clamp/3, digits/2, map_num/2, new_check/2, random_check/1, parse_check/1, flip_check/1, divide_check/2, int_power_check/2, undigits_check/2, map_den_check/2, map_both_check/2, map_seperate_check/3, new/2, from_float/1, parse/1, reduce/1, flip/1, undigits/2, unwrap/1, random/1, divide/2, square_root_check/1, square_root/1, power_check/2, power/2, int_power/2, map_den/2, map_both/2, map_seperate/3, product/1, sum/1]). -export_type([rational/0, undigits_error/0]). -type rational() :: {rational, integer(), integer()}. -type undigits_error() :: base_error | zero_error. -file("/home/benjamin/building/gleam/glatv1/src/glat.gleam", 36). -spec from_int(integer()) -> rational(). from_int(Num) -> {rational, Num, 1}. -file("/home/benjamin/building/gleam/glatv1/src/glat.gleam", 57). -spec from_float_check(float()) -> {ok, rational()} | {error, nil}. from_float_check(F) -> case F of +0.0 -> {error, nil}; _ -> _assert_subject = begin _pipe = gleam@float:to_string(F), gleam@string:split(_pipe, <<"."/utf8>>) end, [Whole_str, Fract_str] = case _assert_subject of [_, _] -> _assert_subject; _assert_fail -> erlang:error(#{gleam_error => let_assert, message => <<"Pattern match failed, no pattern matched the value."/utf8>>, value => _assert_fail, module => <<"glat"/utf8>>, function => <<"from_float_check"/utf8>>, line => 61}) end, Fract_str@1 = case Fract_str of <<"0"/utf8>> -> <<""/utf8>>; X -> X end, Power = gleam@string:length(Fract_str@1), _assert_subject@1 = gleam@int:parse( <> ), {ok, Num} = case _assert_subject@1 of {ok, _} -> _assert_subject@1; _assert_fail@1 -> erlang:error(#{gleam_error => let_assert, message => <<"Pattern match failed, no pattern matched the value."/utf8>>, value => _assert_fail@1, module => <<"glat"/utf8>>, function => <<"from_float_check"/utf8>>, line => 70}) end, Den = glat@util:int_power(10, Power), {ok, {rational, Num, Den}} end. -file("/home/benjamin/building/gleam/glatv1/src/glat.gleam", 99). -spec do_parse(binary()) -> {ok, {integer(), integer()}} | {error, nil}. do_parse(Str) -> case begin _pipe = Str, gleam@string:split(_pipe, <<"/"/utf8>>) end of [Num, Den] -> gleam@result:'try'( gleam@int:parse(Num), fun(Num@1) -> gleam@result:'try'( gleam@int:parse(Den), fun(Den@1) -> {ok, {Num@1, Den@1}} end ) end ); _ -> {error, nil} end. -file("/home/benjamin/building/gleam/glatv1/src/glat.gleam", 112). -spec to_int(rational()) -> integer(). to_int(Rat) -> case erlang:element(3, Rat) of 0 -> 0; Gleam@denominator -> erlang:element(2, Rat) div Gleam@denominator end. -file("/home/benjamin/building/gleam/glatv1/src/glat.gleam", 118). -spec to_int_floor(rational()) -> integer(). to_int_floor(Rat) -> _pipe = erlang:element(2, Rat), _pipe@1 = gleam@int:floor_divide(_pipe, erlang:element(3, Rat)), gleam@result:unwrap(_pipe@1, 0). -file("/home/benjamin/building/gleam/glatv1/src/glat.gleam", 123). -spec to_float(rational()) -> float(). to_float(Rat) -> case gleam@int:to_float(erlang:element(3, Rat)) of +0.0 -> +0.0; -0.0 -> -0.0; Gleam@denominator -> gleam@int:to_float(erlang:element(2, Rat)) / Gleam@denominator end. -file("/home/benjamin/building/gleam/glatv1/src/glat.gleam", 128). -spec to_string(rational()) -> binary(). to_string(Rat) -> <<<<(gleam@int:to_string(erlang:element(2, Rat)))/binary, "/"/utf8>>/binary, (gleam@int:to_string(erlang:element(3, Rat)))/binary>>. -file("/home/benjamin/building/gleam/glatv1/src/glat.gleam", 132). -spec is_negative(rational()) -> boolean(). is_negative(Rat) -> erlang:element(2, Rat) < 0. -file("/home/benjamin/building/gleam/glatv1/src/glat.gleam", 136). -spec is_positive(rational()) -> boolean(). is_positive(Rat) -> erlang:element(2, Rat) >= 0. -file("/home/benjamin/building/gleam/glatv1/src/glat.gleam", 147). -spec absolute_value(rational()) -> rational(). absolute_value(Rat) -> erlang:setelement(2, Rat, gleam@int:absolute_value(erlang:element(2, Rat))). -file("/home/benjamin/building/gleam/glatv1/src/glat.gleam", 190). -spec remainder(rational()) -> integer(). remainder(Rat) -> _assert_subject = gleam@int:remainder( erlang:element(2, Rat), erlang:element(3, Rat) ), {ok, Num} = 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 => <<"glat"/utf8>>, function => <<"remainder"/utf8>>, line => 191}) end, Num. -file("/home/benjamin/building/gleam/glatv1/src/glat.gleam", 197). -spec modulo(rational()) -> integer(). modulo(Rat) -> _assert_subject = gleam@int:modulo( erlang:element(2, Rat), erlang:element(3, Rat) ), {ok, Num} = 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 => <<"glat"/utf8>>, function => <<"modulo"/utf8>>, line => 198}) end, Num. -file("/home/benjamin/building/gleam/glatv1/src/glat.gleam", 204). -spec fraction(rational()) -> rational(). fraction(Rat) -> {rational, remainder(Rat), erlang:element(3, Rat)}. -file("/home/benjamin/building/gleam/glatv1/src/glat.gleam", 210). -spec fraction_floor(rational()) -> rational(). fraction_floor(Rat) -> {rational, modulo(Rat), erlang:element(3, Rat)}. -file("/home/benjamin/building/gleam/glatv1/src/glat.gleam", 215). -spec floor(rational()) -> rational(). floor(Rat) -> case remainder(Rat) of 0 -> Rat; Rem -> case is_positive(Rat) of true -> {rational, erlang:element(2, Rat) - Rem, erlang:element(3, Rat)}; false -> {rational, (erlang:element(2, Rat) - Rem) - erlang:element(3, Rat), erlang:element(3, Rat)} end end. -file("/home/benjamin/building/gleam/glatv1/src/glat.gleam", 229). -spec ceiling(rational()) -> rational(). ceiling(Rat) -> case remainder(Rat) of 0 -> Rat; Rem -> case is_positive(Rat) of true -> {rational, (erlang:element(2, Rat) - Rem) + erlang:element(3, Rat), erlang:element(3, Rat)}; false -> {rational, erlang:element(2, Rat) - Rem, erlang:element(3, Rat)} end end. -file("/home/benjamin/building/gleam/glatv1/src/glat.gleam", 249). -spec negate(rational()) -> rational(). negate(Rat) -> {rational, - erlang:element(2, Rat), erlang:element(3, Rat)}. -file("/home/benjamin/building/gleam/glatv1/src/glat.gleam", 253). -spec compare(rational(), rational()) -> gleam@order:order(). compare(Lhs, Rhs) -> gleam@int:compare( erlang:element(2, Lhs) * erlang:element(3, Rhs), erlang:element(3, Lhs) * erlang:element(2, Rhs) ). -file("/home/benjamin/building/gleam/glatv1/src/glat.gleam", 241). -spec round(rational()) -> rational(). round(Rat) -> _pipe = Rat, case compare(Rat, {rational, 1, 2}) of gt -> fun ceiling/1; eq -> fun ceiling/1; lt -> fun floor/1 end(_pipe). -file("/home/benjamin/building/gleam/glatv1/src/glat.gleam", 257). -spec add(rational(), rational()) -> rational(). add(Lhs, Rhs) -> case erlang:element(3, Lhs) =:= erlang:element(3, Rhs) of true -> {rational, erlang:element(2, Lhs) + erlang:element(2, Rhs), erlang:element(3, Lhs)}; false -> {rational, (erlang:element(2, Lhs) * erlang:element(3, Rhs)) + (erlang:element( 3, Lhs ) * erlang:element(2, Rhs)), erlang:element(3, Lhs) * erlang:element(3, Rhs)} end. -file("/home/benjamin/building/gleam/glatv1/src/glat.gleam", 265). -spec subtract(rational(), rational()) -> rational(). subtract(Lhs, Rhs) -> case erlang:element(3, Lhs) =:= erlang:element(3, Rhs) of true -> {rational, erlang:element(2, Lhs) - erlang:element(2, Rhs), erlang:element(3, Lhs)}; false -> {rational, (erlang:element(2, Lhs) * erlang:element(3, Rhs)) - (erlang:element( 3, Lhs ) * erlang:element(2, Rhs)), erlang:element(3, Lhs) * erlang:element(3, Rhs)} end. -file("/home/benjamin/building/gleam/glatv1/src/glat.gleam", 273). -spec multiply(rational(), rational()) -> rational(). multiply(Lhs, Rhs) -> {rational, erlang:element(2, Lhs) * erlang:element(2, Rhs), erlang:element(3, Lhs) * erlang:element(3, Rhs)}. -file("/home/benjamin/building/gleam/glatv1/src/glat.gleam", 294). -spec max(rational(), rational()) -> rational(). max(Rat1, Rat2) -> case compare(Rat1, Rat2) of lt -> Rat2; _ -> Rat1 end. -file("/home/benjamin/building/gleam/glatv1/src/glat.gleam", 303). -spec min(rational(), rational()) -> rational(). min(Rat1, Rat2) -> case compare(Rat1, Rat2) of gt -> Rat2; _ -> Rat1 end. -file("/home/benjamin/building/gleam/glatv1/src/glat.gleam", 312). -spec clamp(rational(), rational(), rational()) -> rational(). clamp(Rat, Min_bound, Max_bound) -> _pipe = Rat, _pipe@1 = min(_pipe, Max_bound), max(_pipe@1, Min_bound). -file("/home/benjamin/building/gleam/glatv1/src/glat.gleam", 361). -spec digits(rational(), integer()) -> {ok, {list(integer()), list(integer())}} | {error, nil}. digits(Rat, Base) -> case {gleam@int:digits(erlang:element(2, Rat), Base), gleam@int:digits(erlang:element(3, Rat), Base)} of {{ok, Num}, {ok, Den}} -> {ok, {Num, Den}}; {_, _} -> {error, nil} end. -file("/home/benjamin/building/gleam/glatv1/src/glat.gleam", 414). -spec map_num(rational(), fun((integer()) -> integer())) -> rational(). map_num(Rat, Fun) -> {rational, Fun(erlang:element(2, Rat)), erlang:element(3, Rat)}. -file("/home/benjamin/building/gleam/glatv1/src/glat.gleam", 462). -spec shift_negative(rational()) -> rational(). shift_negative(Rat) -> case erlang:element(3, Rat) < 0 of true -> {rational, gleam@int:negate(erlang:element(2, Rat)), gleam@int:negate(erlang:element(3, Rat))}; false -> Rat end. -file("/home/benjamin/building/gleam/glatv1/src/glat.gleam", 23). -spec new_check(integer(), integer()) -> {ok, rational()} | {error, nil}. new_check(Num, Den) -> case Den of 0 -> {error, nil}; _ -> {ok, begin _pipe = {rational, Num, Den}, shift_negative(_pipe) end} end. -file("/home/benjamin/building/gleam/glatv1/src/glat.gleam", 44). -spec random_check(integer()) -> {ok, rational()} | {error, nil}. random_check(Den) -> new_check(gleam@int:random(gleam@int:absolute_value(Den) + 1), Den). -file("/home/benjamin/building/gleam/glatv1/src/glat.gleam", 85). -spec parse_check(binary()) -> {ok, rational()} | {error, nil}. parse_check(Str) -> gleam@result:'try'( do_parse(Str), fun(_use0) -> {Num, Den} = _use0, new_check(Num, Den) end ). -file("/home/benjamin/building/gleam/glatv1/src/glat.gleam", 154). -spec flip_check(rational()) -> {ok, rational()} | {error, nil}. flip_check(Rat) -> new_check(erlang:element(3, Rat), erlang:element(2, Rat)). -file("/home/benjamin/building/gleam/glatv1/src/glat.gleam", 281). -spec divide_check(rational(), rational()) -> {ok, rational()} | {error, nil}. divide_check(Lhs, Rhs) -> _pipe = flip_check(Rhs), gleam@result:map(_pipe, fun(_capture) -> multiply(Lhs, _capture) end). -file("/home/benjamin/building/gleam/glatv1/src/glat.gleam", 336). -spec int_power_check(integer(), integer()) -> {ok, rational()} | {error, nil}. int_power_check(Base, Exponent) -> case Exponent >= 0 of true -> _pipe = glat@util:int_power(Base, Exponent), _pipe@1 = from_int(_pipe), {ok, _pipe@1}; false -> new_check(1, glat@util:int_power(Base, gleam@int:negate(Exponent))) end. -file("/home/benjamin/building/gleam/glatv1/src/glat.gleam", 396). -spec do_undigits({list(integer()), list(integer())}, integer()) -> {ok, rational()} | {error, undigits_error()}. do_undigits(Tup, Base) -> gleam@result:'try'( begin _pipe = gleam@int:undigits(erlang:element(1, Tup), Base), gleam@result:replace_error(_pipe, base_error) end, fun(Num) -> gleam@result:'try'( begin _pipe@1 = gleam@int:undigits(erlang:element(2, Tup), Base), gleam@result:replace_error(_pipe@1, base_error) end, fun(Den) -> _pipe@2 = new_check(Num, Den), gleam@result:replace_error(_pipe@2, zero_error) end ) end ). -file("/home/benjamin/building/gleam/glatv1/src/glat.gleam", 373). -spec undigits_check({list(integer()), list(integer())}, integer()) -> {ok, rational()} | {error, nil}. undigits_check(Tup, Base) -> _pipe = do_undigits(Tup, Base), gleam@result:nil_error(_pipe). -file("/home/benjamin/building/gleam/glatv1/src/glat.gleam", 418). -spec map_den_check(rational(), fun((integer()) -> integer())) -> {ok, rational()} | {error, nil}. map_den_check(Rat, Fun) -> new_check(erlang:element(2, Rat), Fun(erlang:element(3, Rat))). -file("/home/benjamin/building/gleam/glatv1/src/glat.gleam", 429). -spec map_both_check(rational(), fun((integer()) -> integer())) -> {ok, rational()} | {error, nil}. map_both_check(Rat, Fun) -> new_check(Fun(erlang:element(2, Rat)), Fun(erlang:element(3, Rat))). -file("/home/benjamin/building/gleam/glatv1/src/glat.gleam", 440). -spec map_seperate_check( rational(), fun((integer()) -> integer()), fun((integer()) -> integer()) ) -> {ok, rational()} | {error, nil}. map_seperate_check(Rat, Fun1, Fun2) -> new_check(Fun1(erlang:element(2, Rat)), Fun2(erlang:element(3, Rat))). -file("/home/benjamin/building/gleam/glatv1/src/glat.gleam", 31). -spec new(integer(), integer()) -> rational(). new(Num, Den) -> _pipe = new_check(Num, Den), gleam@result:unwrap(_pipe, {rational, 0, 1}). -file("/home/benjamin/building/gleam/glatv1/src/glat.gleam", 78). -spec from_float(float()) -> rational(). from_float(F) -> _pipe = from_float_check(F), gleam@result:unwrap(_pipe, {rational, 0, 1}). -file("/home/benjamin/building/gleam/glatv1/src/glat.gleam", 94). -spec parse(binary()) -> {ok, rational()} | {error, nil}. parse(Str) -> gleam@result:map( do_parse(Str), fun(_use0) -> {Num, Den} = _use0, new(Num, Den) end ). -file("/home/benjamin/building/gleam/glatv1/src/glat.gleam", 141). -spec reduce(rational()) -> rational(). reduce(Rat) -> Gcd = glat@util:gcd(erlang:element(2, Rat), erlang:element(3, Rat)), new(case Gcd of 0 -> 0; Gleam@denominator -> erlang:element(2, Rat) div Gleam@denominator end, case Gcd of 0 -> 0; Gleam@denominator@1 -> erlang:element(3, Rat) div Gleam@denominator@1 end). -file("/home/benjamin/building/gleam/glatv1/src/glat.gleam", 161). -spec flip(rational()) -> rational(). flip(Rat) -> _pipe = flip_check(Rat), gleam@result:unwrap(_pipe, {rational, 0, 1}). -file("/home/benjamin/building/gleam/glatv1/src/glat.gleam", 385). -spec undigits({list(integer()), list(integer())}, integer()) -> {ok, rational()} | {error, nil}. undigits(Tup, Base) -> case do_undigits(Tup, Base) of {ok, Rat} -> {ok, Rat}; {error, zero_error} -> {ok, {rational, 0, 1}}; _ -> {error, nil} end. -file("/home/benjamin/building/gleam/glatv1/src/glat.gleam", 457). -spec unwrap({ok, rational()} | {error, nil}) -> rational(). unwrap(Res) -> gleam@result:unwrap(Res, {rational, 0, 1}). -file("/home/benjamin/building/gleam/glatv1/src/glat.gleam", 52). -spec random(integer()) -> rational(). random(Den) -> unwrap(random_check(Den)). -file("/home/benjamin/building/gleam/glatv1/src/glat.gleam", 289). -spec divide(rational(), rational()) -> rational(). divide(Lhs, Rhs) -> unwrap(divide_check(Lhs, Rhs)). -file("/home/benjamin/building/gleam/glatv1/src/glat.gleam", 169). -spec square_root_check(rational()) -> {ok, rational()} | {error, nil}. square_root_check(Rat) -> case erlang:element(2, Rat) of 0 -> {ok, Rat}; _ -> gleam@result:'try'( gleam@int:square_root(erlang:element(2, Rat)), fun(Num) -> gleam@result:'try'( gleam@int:square_root(erlang:element(3, Rat)), fun(Den) -> {ok, divide(from_float(Num), from_float(Den))} end ) end ) end. -file("/home/benjamin/building/gleam/glatv1/src/glat.gleam", 184). -spec square_root(rational()) -> rational(). square_root(Rat) -> _pipe = square_root_check(Rat), gleam@result:unwrap(_pipe, {rational, 0, 1}). -file("/home/benjamin/building/gleam/glatv1/src/glat.gleam", 322). -spec power_check(rational(), integer()) -> {ok, rational()} | {error, nil}. power_check(Rat, Exponent) -> gleam@result:'try'( int_power_check(erlang:element(2, Rat), Exponent), fun(Num) -> gleam@result:map( int_power_check(erlang:element(3, Rat), Exponent), fun(Den) -> divide(Num, Den) end ) end ). -file("/home/benjamin/building/gleam/glatv1/src/glat.gleam", 330). -spec power(rational(), integer()) -> rational(). power(Rat, Exponent) -> unwrap(power_check(Rat, Exponent)). -file("/home/benjamin/building/gleam/glatv1/src/glat.gleam", 345). -spec int_power(integer(), integer()) -> rational(). int_power(Base, Exponent) -> unwrap(int_power_check(Base, Exponent)). -file("/home/benjamin/building/gleam/glatv1/src/glat.gleam", 425). -spec map_den(rational(), fun((integer()) -> integer())) -> rational(). map_den(Rat, Fun) -> unwrap(map_den_check(Rat, Fun)). -file("/home/benjamin/building/gleam/glatv1/src/glat.gleam", 436). -spec map_both(rational(), fun((integer()) -> integer())) -> rational(). map_both(Rat, Fun) -> unwrap(map_both_check(Rat, Fun)). -file("/home/benjamin/building/gleam/glatv1/src/glat.gleam", 448). -spec map_seperate( rational(), fun((integer()) -> integer()), fun((integer()) -> integer()) ) -> rational(). map_seperate(Rat, Fun1, Fun2) -> unwrap(map_seperate_check(Rat, Fun1, Fun2)). -file("/home/benjamin/building/gleam/glatv1/src/glat.gleam", 350). -spec product(list(rational())) -> rational(). product(Rats) -> gleam@list:fold(Rats, {rational, 1, 1}, fun multiply/2). -file("/home/benjamin/building/gleam/glatv1/src/glat.gleam", 355). -spec sum(list(rational())) -> rational(). sum(Rats) -> gleam@list:fold(Rats, {rational, 1, 1}, fun add/2).