-module(ieee_float). -compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch, inline]). -define(FILEPATH, "src/ieee_float.gleam"). -export([finite/1, positive_infinity/0, negative_infinity/0, nan/0, is_finite/1, is_nan/1, to_finite/1, to_string/1, parse/1, to_bytes_16_le/1, from_bytes_16_le/1, to_bytes_16_be/1, from_bytes_16_be/1, to_bytes_32_le/1, from_bytes_32_le/1, to_bytes_32_be/1, from_bytes_32_be/1, to_bytes_64_le/1, from_bytes_64_le/1, to_bytes_64_be/1, from_bytes_64_be/1, absolute_value/1, add/2, ceiling/1, max/2, min/2, clamp/3, compare/2, divide/2, floor/1, multiply/2, negate/1, power/2, random/0, round/1, square_root/1, subtract/2]). -export_type([i_e_e_e_float/0, sign/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. -opaque i_e_e_e_float() :: {finite, float()} | {infinite, sign()} | na_n. -type sign() :: positive | negative. -file("src/ieee_float.gleam", 28). ?DOC(" Creates a new `IEEEFloat` from a `Float`.\n"). -spec finite(float()) -> i_e_e_e_float(). finite(F) -> {finite, F}. -file("src/ieee_float.gleam", 35). ?DOC(" Returns the positive infinity value.\n"). -spec positive_infinity() -> i_e_e_e_float(). positive_infinity() -> {infinite, positive}. -file("src/ieee_float.gleam", 42). ?DOC(" Returns the negative infinity value.\n"). -spec negative_infinity() -> i_e_e_e_float(). negative_infinity() -> {infinite, negative}. -file("src/ieee_float.gleam", 49). ?DOC(" Returns the NaN (Not a Number) value.\n"). -spec nan() -> i_e_e_e_float(). nan() -> na_n. -file("src/ieee_float.gleam", 57). ?DOC( " Returns whether an `IEEEFloat` is finite. If it isn't finite it is either\n" " infinite or NaN.\n" ). -spec is_finite(i_e_e_e_float()) -> boolean(). is_finite(F) -> case F of {finite, _} -> true; _ -> false end. -file("src/ieee_float.gleam", 68). ?DOC( " Returns whether an `IEEEFloat` is NaN. If it isn't NaN it is either finite\n" " or infinite.\n" ). -spec is_nan(i_e_e_e_float()) -> boolean(). is_nan(F) -> F =:= na_n. -file("src/ieee_float.gleam", 76). ?DOC( " Converts an `IEEEFloat` to the native `Float` type. If the `IEEEFloat` is\n" " infinite or NaN then `Error(Nil)` is returned.\n" ). -spec to_finite(i_e_e_e_float()) -> {ok, float()} | {error, nil}. to_finite(F) -> case F of {finite, Value} -> {ok, Value}; _ -> {error, nil} end. -file("src/ieee_float.gleam", 86). ?DOC(" Formats an `IEEEFloat` as a string.\n"). -spec to_string(i_e_e_e_float()) -> binary(). to_string(F) -> case F of {finite, F@1} -> gleam_stdlib:float_to_string(F@1); {infinite, positive} -> <<"Infinity"/utf8>>; {infinite, negative} -> <<"-Infinity"/utf8>>; na_n -> <<"NaN"/utf8>> end. -file("src/ieee_float.gleam", 99). ?DOC( " Parses a string to an `IEEEFloat`. If the string is not a valid float then\n" " NaN is returned.\n" ). -spec parse(binary()) -> i_e_e_e_float(). parse(S) -> case gleam@string:trim(S) of <<"Infinity"/utf8>> -> {infinite, positive}; <<"-Infinity"/utf8>> -> {infinite, negative}; S@1 -> case gleam_stdlib:parse_float(S@1) of {ok, F} -> {finite, F}; _ -> na_n end end. -file("src/ieee_float.gleam", 114). ?DOC(" Converts an `IEEEFloat` to bytes for a little endian 16-bit IEEE 754 float.\n"). -spec to_bytes_16_le(i_e_e_e_float()) -> bitstring(). to_bytes_16_le(F) -> case F of {finite, F@1} -> <>; {infinite, positive} -> <<16#7C00:16/little>>; {infinite, negative} -> <<16#FC00:16/little>>; na_n -> <<16#7E00:16/little>> end. -file("src/ieee_float.gleam", 128). ?DOC( " Converts bytes for a little endian 16-bit IEEE 754 float to an `IEEEFloat`.\n" "\n" " If the bit array doesn't contain exactly two bytes then NaN is returned.\n" ). -spec from_bytes_16_le(bitstring()) -> i_e_e_e_float(). from_bytes_16_le(Bytes) -> case Bytes of <> -> {finite, Value}; <<16#7C00:16/little>> -> {infinite, positive}; <<16#FC00:16/little>> -> {infinite, negative}; _ -> na_n end. -file("src/ieee_float.gleam", 140). ?DOC(" Converts an `IEEEFloat` to bytes for a big endian 16-bit IEEE 754 float.\n"). -spec to_bytes_16_be(i_e_e_e_float()) -> bitstring(). to_bytes_16_be(F) -> case F of {finite, F@1} -> <>; {infinite, positive} -> <<16#7C00:16>>; {infinite, negative} -> <<16#FC00:16>>; na_n -> <<16#7E00:16>> end. -file("src/ieee_float.gleam", 154). ?DOC( " Converts bytes for a big endian 16-bit IEEE 754 float to an `IEEEFloat`.\n" "\n" " If the bit array doesn't contain exactly two bytes then NaN is returned.\n" ). -spec from_bytes_16_be(bitstring()) -> i_e_e_e_float(). from_bytes_16_be(Bytes) -> case Bytes of <> -> {finite, Value}; <<16#7C00:16>> -> {infinite, positive}; <<16#FC00:16>> -> {infinite, negative}; _ -> na_n end. -file("src/ieee_float.gleam", 166). ?DOC(" Converts an `IEEEFloat` to bytes for a little endian 32-bit IEEE 754 float.\n"). -spec to_bytes_32_le(i_e_e_e_float()) -> bitstring(). to_bytes_32_le(F) -> case F of {finite, F@1} -> <>; {infinite, positive} -> <<16#7F800000:32/little>>; {infinite, negative} -> <<16#FF800000:32/little>>; na_n -> <<16#7FC00000:32/little>> end. -file("src/ieee_float.gleam", 180). ?DOC( " Converts bytes for a little endian 32-bit IEEE 754 float to an `IEEEFloat`.\n" "\n" " If the bit array doesn't contain exactly four bytes then NaN is returned.\n" ). -spec from_bytes_32_le(bitstring()) -> i_e_e_e_float(). from_bytes_32_le(Bytes) -> case Bytes of <> -> {finite, Value}; <<16#7F800000:32/little>> -> {infinite, positive}; <<16#FF800000:32/little>> -> {infinite, negative}; _ -> na_n end. -file("src/ieee_float.gleam", 192). ?DOC(" Converts an `IEEEFloat` to bytes for a big endian 32-bit IEEE 754 float.\n"). -spec to_bytes_32_be(i_e_e_e_float()) -> bitstring(). to_bytes_32_be(F) -> case F of {finite, F@1} -> <>; {infinite, positive} -> <<16#7F800000:32>>; {infinite, negative} -> <<16#FF800000:32>>; na_n -> <<16#7FC00000:32>> end. -file("src/ieee_float.gleam", 206). ?DOC( " Converts bytes for a big endian 32-bit IEEE 754 float to an `IEEEFloat`.\n" "\n" " If the bit array doesn't contain exactly four bytes then NaN is returned.\n" ). -spec from_bytes_32_be(bitstring()) -> i_e_e_e_float(). from_bytes_32_be(Bytes) -> case Bytes of <> -> {finite, Value}; <<16#7F800000:32>> -> {infinite, positive}; <<16#FF800000:32>> -> {infinite, negative}; _ -> na_n end. -file("src/ieee_float.gleam", 218). ?DOC(" Converts an `IEEEFloat` to bytes for a little endian 64-bit IEEE 754 float.\n"). -spec to_bytes_64_le(i_e_e_e_float()) -> bitstring(). to_bytes_64_le(F) -> case F of {finite, F@1} -> <>; {infinite, positive} -> <<16#7FF0000000000000:64/little>>; {infinite, negative} -> <<16#FFF0000000000000:64/little>>; na_n -> <<16#7FF8000000000000:64/little>> end. -file("src/ieee_float.gleam", 232). ?DOC( " Converts bytes for a little endian 64-bit IEEE 754 float to an `IEEEFloat`.\n" "\n" " If the bit array doesn't contain exactly eight bytes then NaN is returned.\n" ). -spec from_bytes_64_le(bitstring()) -> i_e_e_e_float(). from_bytes_64_le(Bytes) -> case Bytes of <> -> {finite, Value}; <<16#7FF0000000000000:64/little>> -> {infinite, positive}; <<16#FFF0000000000000:64/little>> -> {infinite, negative}; _ -> na_n end. -file("src/ieee_float.gleam", 244). ?DOC(" Converts an `IEEEFloat` to bytes for a big endian 64-bit IEEE 754 float.\n"). -spec to_bytes_64_be(i_e_e_e_float()) -> bitstring(). to_bytes_64_be(F) -> case F of {finite, F@1} -> <>; {infinite, positive} -> <<16#7FF0000000000000:64>>; {infinite, negative} -> <<16#FFF0000000000000:64>>; na_n -> <<16#7FF8000000000000:64>> end. -file("src/ieee_float.gleam", 258). ?DOC( " Converts bytes for a big endian 64-bit IEEE 754 float to an `IEEEFloat`.\n" "\n" " If the bit array doesn't contain exactly eight bytes then NaN is returned.\n" ). -spec from_bytes_64_be(bitstring()) -> i_e_e_e_float(). from_bytes_64_be(Bytes) -> case Bytes of <> -> {finite, Value}; <<16#7FF0000000000000:64>> -> {infinite, positive}; <<16#FFF0000000000000:64>> -> {infinite, negative}; _ -> na_n end. -file("src/ieee_float.gleam", 281). ?DOC(" Returns the absolute value of an `IEEEFloat`.\n"). -spec absolute_value(i_e_e_e_float()) -> i_e_e_e_float(). absolute_value(F) -> case F of {finite, F@1} -> _pipe = F@1, _pipe@1 = gleam@float:absolute_value(_pipe), {finite, _pipe@1}; {infinite, _} -> {infinite, positive}; na_n -> na_n end. -file("src/ieee_float.gleam", 292). ?DOC(" Adds two `IEEEFloat`s together.\n"). -spec add(i_e_e_e_float(), i_e_e_e_float()) -> i_e_e_e_float(). add(A, B) -> case {A, B} of {{finite, A@1}, {finite, B@1}} -> case ieee_float_ffi:rescue_bad_arith( fun() -> {finite, A@1 + B@1} end ) of {ok, F} -> F; {error, nil} -> case {A@1 >= +0.0, B@1 >= +0.0} of {true, true} -> {infinite, positive}; {false, false} -> {infinite, negative}; {_, _} -> erlang:error(#{gleam_error => panic, message => <<"Unexpected error in ieee_float.add"/utf8>>, file => <>, module => <<"ieee_float"/utf8>>, function => <<"add"/utf8>>, line => 301}) end end; {{infinite, Sign}, {finite, _}} -> {infinite, Sign}; {{finite, _}, {infinite, Sign@1}} -> {infinite, Sign@1}; {{infinite, positive}, {infinite, positive}} -> {infinite, positive}; {{infinite, negative}, {infinite, negative}} -> {infinite, negative}; {{infinite, positive}, {infinite, negative}} -> na_n; {{infinite, negative}, {infinite, positive}} -> na_n; {na_n, _} -> na_n; {_, na_n} -> na_n end. -file("src/ieee_float.gleam", 321). ?DOC(" Rounds an `IEEEFloat` to the next highest whole number.\n"). -spec ceiling(i_e_e_e_float()) -> i_e_e_e_float(). ceiling(F) -> case F of {finite, F@1} -> _pipe = F@1, _pipe@1 = math:ceil(_pipe), {finite, _pipe@1}; _ -> F end. -file("src/ieee_float.gleam", 439). ?DOC(" Compares two `IEEEFloat`s, returning the larger of the two.\n"). -spec max(i_e_e_e_float(), i_e_e_e_float()) -> i_e_e_e_float(). max(A, B) -> case {A, B} of {{finite, A@1}, {finite, B@1}} -> _pipe = gleam@float:max(A@1, B@1), {finite, _pipe}; {{infinite, positive}, _} -> {infinite, positive}; {_, {infinite, positive}} -> {infinite, positive}; {{infinite, negative}, A@2} -> A@2; {A@2, {infinite, negative}} -> A@2; {na_n, _} -> na_n; {_, na_n} -> na_n end. -file("src/ieee_float.gleam", 451). ?DOC(" Compares two `IEEEFloat`s, returning the smaller of the two.\n"). -spec min(i_e_e_e_float(), i_e_e_e_float()) -> i_e_e_e_float(). min(A, B) -> case {A, B} of {{finite, A@1}, {finite, B@1}} -> _pipe = gleam@float:min(A@1, B@1), {finite, _pipe}; {{infinite, negative}, _} -> {infinite, negative}; {_, {infinite, negative}} -> {infinite, negative}; {{infinite, positive}, A@2} -> A@2; {A@2, {infinite, positive}} -> A@2; {na_n, _} -> na_n; {_, na_n} -> na_n end. -file("src/ieee_float.gleam", 330). ?DOC(" Restricts an `IEEEFloat` between a lower and upper bound.\n"). -spec clamp(i_e_e_e_float(), i_e_e_e_float(), i_e_e_e_float()) -> i_e_e_e_float(). clamp(F, Min_bound, Max_bound) -> _pipe = F, _pipe@1 = min(_pipe, Max_bound), max(_pipe@1, Min_bound). -file("src/ieee_float.gleam", 345). ?DOC( " Compares two `IEEEFloat`s, returning an `Order`: `Lt` for lower than, `Eq`\n" " for equals, or `Gt` for greater than. If either value is NaN then\n" " `Error(Nil)` is returned.\n" ). -spec compare(i_e_e_e_float(), i_e_e_e_float()) -> {ok, gleam@order:order()} | {error, nil}. compare(A, B) -> case {A, B} of {{finite, A@1}, {finite, B@1}} -> {ok, gleam@float:compare(A@1, B@1)}; {{finite, _}, {infinite, positive}} -> {ok, lt}; {{infinite, positive}, {finite, _}} -> {ok, gt}; {{finite, _}, {infinite, negative}} -> {ok, gt}; {{infinite, negative}, {finite, _}} -> {ok, lt}; {{infinite, negative}, {infinite, negative}} -> {ok, eq}; {{infinite, negative}, {infinite, positive}} -> {ok, lt}; {{infinite, positive}, {infinite, negative}} -> {ok, gt}; {{infinite, positive}, {infinite, positive}} -> {ok, eq}; {na_n, _} -> {error, nil}; {_, na_n} -> {error, nil} end. -file("src/ieee_float.gleam", 366). ?DOC(" Divides one `IEEEFloat` by another.\n"). -spec divide(i_e_e_e_float(), i_e_e_e_float()) -> i_e_e_e_float(). divide(A, B) -> case {A, B} of {na_n, _} -> na_n; {_, na_n} -> na_n; {{finite, +0.0}, {finite, +0.0}} -> na_n; {{finite, +0.0}, {finite, -0.0}} -> na_n; {{finite, -0.0}, {finite, +0.0}} -> na_n; {{finite, -0.0}, {finite, -0.0}} -> na_n; {{finite, A@1}, {finite, +0.0}} -> case A@1 < +0.0 of true -> {infinite, negative}; false -> {infinite, positive} end; {{finite, A@2}, {finite, -0.0}} -> case A@2 < +0.0 of true -> {infinite, positive}; false -> {infinite, negative} end; {{finite, A@3}, {finite, B@1}} -> case ieee_float_ffi:rescue_bad_arith(fun() -> {finite, case B@1 of +0.0 -> +0.0; -0.0 -> -0.0; Gleam@denominator -> A@3 / Gleam@denominator end} end) of {ok, F} -> F; {error, nil} -> case (A@3 >= +0.0) =:= (B@1 >= +0.0) of true -> {infinite, positive}; false -> {infinite, negative} end end; {{finite, A@4}, {infinite, positive}} -> case A@4 >= +0.0 of true -> {finite, +0.0}; false -> {finite, -0.0} end; {{finite, A@5}, {infinite, negative}} -> case A@5 >= +0.0 of true -> {finite, -0.0}; false -> {finite, +0.0} end; {{infinite, positive}, {finite, B@2}} -> case B@2 >= +0.0 of true -> {infinite, positive}; false -> {infinite, negative} end; {{infinite, negative}, {finite, B@3}} -> case B@3 >= +0.0 of true -> {infinite, negative}; false -> {infinite, positive} end; {{infinite, _}, {infinite, _}} -> na_n end. -file("src/ieee_float.gleam", 429). ?DOC(" Rounds an `IEEEFloat` to the next lowest whole number.\n"). -spec floor(i_e_e_e_float()) -> i_e_e_e_float(). floor(F) -> case F of {finite, F@1} -> _pipe = F@1, _pipe@1 = math:floor(_pipe), {finite, _pipe@1}; _ -> F end. -file("src/ieee_float.gleam", 463). ?DOC(" Multiplies two `IEEEFloat`s together.\n"). -spec multiply(i_e_e_e_float(), i_e_e_e_float()) -> i_e_e_e_float(). multiply(A, B) -> case {A, B} of {na_n, _} -> na_n; {_, na_n} -> na_n; {{finite, A@1}, {finite, B@1}} -> case ieee_float_ffi:rescue_bad_arith( fun() -> {finite, A@1 * B@1} end ) of {ok, F} -> F; {error, nil} -> case (A@1 >= +0.0) =:= (B@1 >= +0.0) of true -> {infinite, positive}; false -> {infinite, negative} end end; {{infinite, positive}, {finite, F@1}} -> case F@1 >= +0.0 of true -> {infinite, positive}; false -> {infinite, negative} end; {{finite, F@1}, {infinite, positive}} -> case F@1 >= +0.0 of true -> {infinite, positive}; false -> {infinite, negative} end; {{infinite, negative}, {finite, F@2}} -> case F@2 >= +0.0 of true -> {infinite, negative}; false -> {infinite, positive} end; {{finite, F@2}, {infinite, negative}} -> case F@2 >= +0.0 of true -> {infinite, negative}; false -> {infinite, positive} end; {{infinite, A@2}, {infinite, B@2}} -> case A@2 =:= B@2 of true -> {infinite, positive}; false -> {infinite, negative} end end. -file("src/ieee_float.gleam", 500). ?DOC(" Returns the negative of an `IEEEFloat`.\n"). -spec negate(i_e_e_e_float()) -> i_e_e_e_float(). negate(F) -> case F of {finite, F@1} -> _pipe = F@1, _pipe@1 = gleam@float:negate(_pipe), {finite, _pipe@1}; {infinite, positive} -> {infinite, negative}; {infinite, negative} -> {infinite, positive}; na_n -> na_n end. -file("src/ieee_float.gleam", 512). ?DOC(" Returns the results of the base being raised to the power of the exponent.\n"). -spec power(i_e_e_e_float(), i_e_e_e_float()) -> i_e_e_e_float(). power(F, Exp) -> case {F, Exp} of {{finite, F@1}, {finite, Exp@1}} -> case ieee_float_ffi:rescue_bad_arith( fun() -> gleam@float:power(F@1, Exp@1) end ) of {ok, F@2} -> _pipe = F@2, _pipe@1 = gleam@result:map( _pipe, fun(Field@0) -> {finite, Field@0} end ), gleam@result:unwrap(_pipe@1, na_n); {error, nil} -> {infinite, positive} end; {na_n, _} -> na_n; {_, na_n} -> na_n; {{infinite, _}, {finite, +0.0}} -> {finite, 1.0}; {{infinite, _}, {finite, -0.0}} -> {finite, 1.0}; {{finite, 1.0}, {infinite, _}} -> na_n; {{finite, -1.0}, {infinite, _}} -> na_n; {{infinite, positive}, {infinite, positive}} -> {infinite, positive}; {{infinite, positive}, {infinite, negative}} -> {finite, +0.0}; {{infinite, negative}, {infinite, positive}} -> {infinite, positive}; {{infinite, negative}, {infinite, negative}} -> {finite, +0.0}; {{infinite, positive}, {finite, F@3}} when F@3 < +0.0 -> {finite, +0.0}; {{finite, +0.0}, {infinite, positive}} -> {finite, +0.0}; {{finite, -0.0}, {infinite, positive}} -> {finite, +0.0}; {{finite, _}, {infinite, positive}} -> {infinite, positive}; {{infinite, positive}, {finite, _}} -> {infinite, positive}; {{finite, F@4}, {infinite, negative}} -> case (F@4 > 1.0) orelse (F@4 < -1.0) of true -> {finite, +0.0}; false -> {infinite, positive} end; {{infinite, negative}, {finite, F@5}} -> case (erlang:float(erlang:round(F@5)) =:= F@5) andalso gleam@int:is_odd( erlang:trunc(F@5) ) of true -> case F@5 < +0.0 of true -> {finite, -0.0}; false -> {infinite, negative} end; false -> case F@5 < +0.0 of true -> {finite, +0.0}; false -> {infinite, positive} end end end. -file("src/ieee_float.gleam", 577). ?DOC( " Generates a random `IEEEFloat` between zero (inclusive) and one (exclusive).\n" "\n" " On the Erlang target this updates the random state in the process\n" " dictionary. See .\n" ). -spec random() -> i_e_e_e_float(). random() -> {finite, rand:uniform()}. -file("src/ieee_float.gleam", 585). ?DOC( " Rounds an `IEEEFloat` to the nearest whole number as an `Int`. If the input\n" " value is not finite then `Error(Nil)` is returned.\n" ). -spec round(i_e_e_e_float()) -> {ok, integer()} | {error, nil}. round(F) -> case F of {finite, F@1} -> _pipe = F@1, _pipe@1 = erlang:round(_pipe), {ok, _pipe@1}; _ -> {error, nil} end. -file("src/ieee_float.gleam", 595). ?DOC(" Returns the square root of an `IEEEFloat`.\n"). -spec square_root(i_e_e_e_float()) -> i_e_e_e_float(). square_root(F) -> power(F, {finite, 0.5}). -file("src/ieee_float.gleam", 602). ?DOC(" Subtracts one `IEEEFloat` from another.\n"). -spec subtract(i_e_e_e_float(), i_e_e_e_float()) -> i_e_e_e_float(). subtract(A, B) -> add(A, negate(B)).