Packages

Arbitrary precision decimal arithmetic for Gleam

Current section

Files

Jump to
bigdecimal src bigdecimal.erl
Raw

src/bigdecimal.erl

-module(bigdecimal).
-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch, inline]).
-define(FILEPATH, "src/bigdecimal.gleam").
-export([unscaled_value/1, scale/1, zero/0, one/0, absolute_value/1, signum/1, precision/1, ulp/1, negate/1, truncate_to_bigint/1, rescale/3, add/2, sum/1, subtract/2, compare/2, clamp/3, multiply/2, product/1, trim_zeros/1, divide/3, remainder/2, power/2, from_string/1, from_float/1, to_plain_string/1]).
-export_type([big_decimal/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 big_decimal() :: {big_decimal, bigi:big_int(), integer()}.
-file("src/bigdecimal.gleam", 17).
-spec unscaled_value(big_decimal()) -> bigi:big_int().
unscaled_value(Value) ->
{big_decimal, Unscaled_value, _} = Value,
Unscaled_value.
-file("src/bigdecimal.gleam", 22).
-spec scale(big_decimal()) -> integer().
scale(Value) ->
{big_decimal, _, Scale} = Value,
Scale.
-file("src/bigdecimal.gleam", 27).
-spec zero() -> big_decimal().
zero() ->
{big_decimal, bigi_ffi:from(0), 0}.
-file("src/bigdecimal.gleam", 31).
-spec one() -> big_decimal().
one() ->
{big_decimal, bigi_ffi:from(1), 0}.
-file("src/bigdecimal.gleam", 49).
-spec absolute_value(big_decimal()) -> big_decimal().
absolute_value(Value) ->
{big_decimal, erlang:abs(unscaled_value(Value)), scale(Value)}.
-file("src/bigdecimal.gleam", 61).
-spec compare_to_zero(big_decimal()) -> gleam@order:order().
compare_to_zero(Value) ->
_pipe = unscaled_value(Value),
bigi_ffi:compare(_pipe, bigi_ffi:zero()).
-file("src/bigdecimal.gleam", 56).
?DOC(
" Sign function. Returns +1 if the value is positive,\n"
" -1 if the value is negative, 0 if the value is zero.\n"
).
-spec signum(big_decimal()) -> integer().
signum(Value) ->
_pipe = compare_to_zero(Value),
gleam@order:to_int(_pipe).
-file("src/bigdecimal.gleam", 37).
?DOC(" The number of digits in the unscaled value.\n").
-spec precision(big_decimal()) -> integer().
precision(Value) ->
String_length = begin
_pipe = unscaled_value(Value),
_pipe@1 = erlang:integer_to_binary(_pipe),
erlang:byte_size(_pipe@1)
end,
case signum(Value) of
-1 ->
String_length - 1;
_ ->
String_length
end.
-file("src/bigdecimal.gleam", 68).
?DOC(" Returns the unit of least precision of this `BigDecimal`.\n").
-spec ulp(big_decimal()) -> big_decimal().
ulp(Value) ->
{big_decimal, bigi_ffi:from(1), scale(Value)}.
-file("src/bigdecimal.gleam", 72).
-spec negate(big_decimal()) -> big_decimal().
negate(Value) ->
{big_decimal, bigi_ffi:negate(unscaled_value(Value)), scale(Value)}.
-file("src/bigdecimal.gleam", 210).
-spec is_even(bigi:big_int()) -> boolean().
is_even(Value) ->
case begin
_pipe = bigi_ffi:modulo(Value, bigi_ffi:from(2)),
bigi_ffi:to(_pipe)
end of
{ok, 0} ->
true;
_ ->
false
end.
-file("src/bigdecimal.gleam", 220).
-spec get_magnitude(bigi:big_int(), integer()) -> integer().
get_magnitude(Value, Magnitude) ->
Quotient = bigi_ffi:divide(Value, bigi_ffi:from(10)),
case bigi_ffi:compare(Quotient, bigi_ffi:zero()) of
lt ->
get_magnitude(Quotient, Magnitude + 1);
gt ->
get_magnitude(Quotient, Magnitude + 1);
eq ->
Magnitude
end.
-file("src/bigdecimal.gleam", 274).
-spec multiply_power_of_ten(bigi:big_int(), integer()) -> bigi:big_int().
multiply_power_of_ten(Value, N) ->
case N >= 0 of
true -> nil;
_assert_fail ->
erlang:error(#{gleam_error => let_assert,
message => <<"Pattern match failed, no pattern matched the value."/utf8>>,
file => <<?FILEPATH/utf8>>,
module => <<"bigdecimal"/utf8>>,
function => <<"multiply_power_of_ten"/utf8>>,
line => 275,
value => _assert_fail,
start => 6788,
'end' => 6812,
pattern_start => 6799,
pattern_end => 6803})
end,
_pipe = bigi_ffi:from(10),
_pipe@1 = bigi_ffi:power(_pipe, bigi_ffi:from(N)),
_pipe@2 = gleam@result:lazy_unwrap(_pipe@1, fun() -> bigi_ffi:from(0) end),
bigi_ffi:multiply(_pipe@2, Value).
-file("src/bigdecimal.gleam", 84).
?DOC(" Truncate the `BigDecimal` to a `BigInt`.\n").
-spec truncate_to_bigint(big_decimal()) -> bigi:big_int().
truncate_to_bigint(Value) ->
_pipe = unscaled_value(Value),
bigi_ffi:divide(
_pipe,
multiply_power_of_ten(bigi_ffi:from(1), scale(Value))
).
-file("src/bigdecimal.gleam", 130).
-spec add_zeros(big_decimal(), integer(), integer()) -> big_decimal().
add_zeros(Value, New_scale, Scale_diff) ->
_pipe = unscaled_value(Value),
_pipe@1 = multiply_power_of_ten(_pipe, Scale_diff),
{big_decimal, _pipe@1, New_scale}.
-file("src/bigdecimal.gleam", 182).
-spec calculate_adjustment_for_half_round(
bigi:big_int(),
integer(),
bigi:big_int(),
bigi:big_int(),
bigdecimal@rounding:rounding_mode()
) -> bigi:big_int().
calculate_adjustment_for_half_round(
Unscaled_value,
Sign,
Quotient,
Power_of_ten,
Rounding
) ->
Remainder = begin
_pipe = bigi_ffi:multiply(Quotient, Power_of_ten),
_pipe@1 = bigi_ffi:subtract(_pipe, Unscaled_value),
erlang:abs(_pipe@1)
end,
To_compare = begin
_pipe@2 = get_magnitude(Remainder, 0),
multiply_power_of_ten(bigi_ffi:from(5), _pipe@2)
end,
case {bigi_ffi:compare(Remainder, To_compare), Rounding} of
{eq, half_even} ->
case is_even(Quotient) of
true ->
bigi_ffi:zero();
false ->
bigi_ffi:from(Sign)
end;
{eq, half_up} ->
bigi_ffi:from(Sign);
{gt, _} ->
bigi_ffi:from(Sign);
{_, _} ->
bigi_ffi:zero()
end.
-file("src/bigdecimal.gleam", 156).
-spec adjust_unscaled_value_for_rounding(
bigi:big_int(),
integer(),
bigi:big_int(),
bigi:big_int(),
bigdecimal@rounding:rounding_mode()
) -> bigi:big_int().
adjust_unscaled_value_for_rounding(
Unscaled_value,
Quotient_sign,
Quotient,
Divisor,
Rounding
) ->
Adjustment = case {Rounding, Quotient_sign} of
{floor, S} when S < 0 ->
bigi_ffi:from(-1);
{ceiling, S@1} when S@1 > 0 ->
bigi_ffi:from(1);
{up, S@2} ->
bigi_ffi:from(S@2);
{half_up, S@3} when S@3 =/= 0 ->
calculate_adjustment_for_half_round(
Unscaled_value,
S@3,
Quotient,
Divisor,
Rounding
);
{half_down, S@3} when S@3 =/= 0 ->
calculate_adjustment_for_half_round(
Unscaled_value,
S@3,
Quotient,
Divisor,
Rounding
);
{half_even, S@3} when S@3 =/= 0 ->
calculate_adjustment_for_half_round(
Unscaled_value,
S@3,
Quotient,
Divisor,
Rounding
);
{_, _} ->
bigi_ffi:zero()
end,
_pipe = Quotient,
bigi_ffi:add(_pipe, Adjustment).
-file("src/bigdecimal.gleam", 136).
-spec rescale_with_rounding(
big_decimal(),
integer(),
integer(),
bigdecimal@rounding:rounding_mode()
) -> big_decimal().
rescale_with_rounding(Value, New_scale, Scale_diff, Rounding) ->
Tens = multiply_power_of_ten(bigi_ffi:from(1), Scale_diff),
Unscaled = unscaled_value(Value),
Quotient = bigi_ffi:divide(Unscaled, Tens),
_pipe = adjust_unscaled_value_for_rounding(
Unscaled,
signum(Value),
Quotient,
Tens,
Rounding
),
{big_decimal, _pipe, New_scale}.
-file("src/bigdecimal.gleam", 117).
-spec rescale(big_decimal(), integer(), bigdecimal@rounding:rounding_mode()) -> big_decimal().
rescale(Value, New_scale, Rounding) ->
Scale_diff = scale(Value) - New_scale,
case gleam@int:compare(Scale_diff, 0) of
eq ->
Value;
lt ->
add_zeros(Value, New_scale, - Scale_diff);
gt ->
rescale_with_rounding(Value, New_scale, Scale_diff, Rounding)
end.
-file("src/bigdecimal.gleam", 263).
-spec scale_adjusted_add(big_decimal(), big_decimal(), integer()) -> big_decimal().
scale_adjusted_add(To_scale, To_add, Scale_difference) ->
_pipe = unscaled_value(To_scale),
_pipe@1 = multiply_power_of_ten(_pipe, Scale_difference),
_pipe@2 = bigi_ffi:add(_pipe@1, unscaled_value(To_add)),
{big_decimal, _pipe@2, scale(To_add)}.
-file("src/bigdecimal.gleam", 228).
-spec add(big_decimal(), big_decimal()) -> big_decimal().
add(Augend, Addend) ->
case gleam@int:subtract(scale(Augend), scale(Addend)) of
Scale_difference when Scale_difference < 0 ->
scale_adjusted_add(Augend, Addend, - Scale_difference);
Scale_difference@1 when Scale_difference@1 > 0 ->
scale_adjusted_add(Addend, Augend, Scale_difference@1);
_ ->
{big_decimal,
bigi_ffi:add(unscaled_value(Augend), unscaled_value(Addend)),
scale(Augend)}
end.
-file("src/bigdecimal.gleam", 242).
-spec sum(list(big_decimal())) -> big_decimal().
sum(Values) ->
gleam@list:fold(Values, zero(), fun add/2).
-file("src/bigdecimal.gleam", 249).
-spec subtract(big_decimal(), big_decimal()) -> big_decimal().
subtract(Minuend, Subtrahend) ->
case gleam@int:subtract(scale(Minuend), scale(Subtrahend)) of
Scale_difference when Scale_difference < 0 ->
scale_adjusted_add(Minuend, negate(Subtrahend), - Scale_difference);
Scale_difference@1 when Scale_difference@1 > 0 ->
scale_adjusted_add(negate(Subtrahend), Minuend, Scale_difference@1);
_ ->
{big_decimal,
bigi_ffi:subtract(
unscaled_value(Minuend),
unscaled_value(Subtrahend)
),
scale(Minuend)}
end.
-file("src/bigdecimal.gleam", 297).
-spec scale_adjusted_compare(big_decimal(), big_decimal(), integer()) -> gleam@order:order().
scale_adjusted_compare(To_scale, To_compare, Scale_difference) ->
Compare_order@1 = case begin
_pipe = gleam@int:absolute_value(Scale_difference),
_pipe@1 = bigi_ffi:from(_pipe),
_pipe@2 = bigi_ffi:power(bigi_ffi:from(10), _pipe@1),
_pipe@3 = gleam@result:map(
_pipe@2,
fun(_capture) ->
bigi_ffi:multiply(_capture, unscaled_value(To_scale))
end
),
gleam@result:map(
_pipe@3,
fun(_capture@1) ->
bigi_ffi:compare(_capture@1, unscaled_value(To_compare))
end
)
end of
{ok, Compare_order} -> Compare_order;
_assert_fail ->
erlang:error(#{gleam_error => let_assert,
message => <<"Pattern match failed, no pattern matched the value."/utf8>>,
file => <<?FILEPATH/utf8>>,
module => <<"bigdecimal"/utf8>>,
function => <<"scale_adjusted_compare"/utf8>>,
line => 303,
value => _assert_fail,
start => 7650,
'end' => 7907,
pattern_start => 7661,
pattern_end => 7678})
end,
Compare_order@1.
-file("src/bigdecimal.gleam", 286).
?DOC(" N.B. If scale is different, trailing zeros are ignored.\n").
-spec compare(big_decimal(), big_decimal()) -> gleam@order:order().
compare(This, That) ->
case gleam@int:subtract(scale(This), scale(That)) of
Scale_difference when Scale_difference < 0 ->
scale_adjusted_compare(This, That, Scale_difference);
Scale_difference@1 when Scale_difference@1 > 0 ->
_pipe = scale_adjusted_compare(That, This, Scale_difference@1),
gleam@order:negate(_pipe);
_ ->
bigi_ffi:compare(unscaled_value(This), unscaled_value(That))
end.
-file("src/bigdecimal.gleam", 92).
?DOC(
" N.B. if the input has equal value to either of the extremes\n"
" but different precision, the larger precision will be returned\n"
).
-spec clamp(big_decimal(), big_decimal(), big_decimal()) -> big_decimal().
clamp(Value, Min, Max) ->
case compare(Value, Min) of
eq ->
case gleam@int:compare(scale(Value), scale(Min)) of
eq ->
Value;
gt ->
Value;
lt ->
Min
end;
lt ->
Min;
gt ->
case compare(Value, Max) of
eq ->
case gleam@int:compare(scale(Value), scale(Max)) of
eq ->
Value;
lt ->
Value;
gt ->
Max
end;
gt ->
Max;
lt ->
Value
end
end.
-file("src/bigdecimal.gleam", 312).
-spec multiply(big_decimal(), big_decimal()) -> big_decimal().
multiply(Multiplicand, Multiplier) ->
{big_decimal,
bigi_ffi:multiply(
unscaled_value(Multiplicand),
unscaled_value(Multiplier)
),
gleam@int:add(scale(Multiplicand), scale(Multiplier))}.
-file("src/bigdecimal.gleam", 324).
?DOC(" For an empty list, this will return `one()`.\n").
-spec product(list(big_decimal())) -> big_decimal().
product(Values) ->
gleam@list:fold(Values, one(), fun multiply/2).
-file("src/bigdecimal.gleam", 377).
-spec divide_and_round(
bigi:big_int(),
bigi:big_int(),
integer(),
bigdecimal@rounding:rounding_mode()
) -> big_decimal().
divide_and_round(Dividend, Divisor, Scale, Rounding) ->
Quotient = bigi_ffi:divide(Dividend, Divisor),
Quotient_sign = begin
_pipe = bigi_ffi:compare(Quotient, bigi_ffi:zero()),
gleam@order:to_int(_pipe)
end,
Remainder = bigi_ffi:remainder(Dividend, Divisor),
case bigi_ffi:compare(Remainder, bigi_ffi:zero()) of
eq ->
{big_decimal, Quotient, Scale};
lt ->
_pipe@1 = adjust_unscaled_value_for_rounding(
Dividend,
Quotient_sign,
Quotient,
Divisor,
Rounding
),
{big_decimal, _pipe@1, Scale};
gt ->
_pipe@1 = adjust_unscaled_value_for_rounding(
Dividend,
Quotient_sign,
Quotient,
Divisor,
Rounding
),
{big_decimal, _pipe@1, Scale}
end.
-file("src/bigdecimal.gleam", 408).
?DOC(
" trims trailing zeros until the requested scale\n"
" is reached or no more zeros can be trimmed\n"
).
-spec trim_zeros_to_match_scale(big_decimal(), integer()) -> big_decimal().
trim_zeros_to_match_scale(Value, Preferred_scale) ->
case scale(Value) > Preferred_scale of
false ->
Value;
true ->
Non_zero_remainder = begin
_pipe = unscaled_value(Value),
_pipe@1 = bigi_ffi:remainder(_pipe, bigi_ffi:from(10)),
bigi_ffi:compare(_pipe@1, bigi_ffi:zero())
end
/= eq,
case Non_zero_remainder of
true ->
Value;
false ->
trim_zeros_to_match_scale(
begin
_pipe@2 = unscaled_value(Value),
_pipe@3 = bigi_ffi:divide(
_pipe@2,
bigi_ffi:from(10)
),
{big_decimal, _pipe@3, scale(Value) - 1}
end,
Preferred_scale
)
end
end.
-file("src/bigdecimal.gleam", 78).
?DOC(" Trim trailing zeros from after the decimal point.\n").
-spec trim_zeros(big_decimal()) -> big_decimal().
trim_zeros(Value) ->
trim_zeros_to_match_scale(Value, 0).
-file("src/bigdecimal.gleam", 348).
-spec divide_internal(
big_decimal(),
big_decimal(),
integer(),
bigdecimal@rounding:rounding_mode()
) -> big_decimal().
divide_internal(Dividend, Divisor, Preferred_scale, Rounding) ->
New_scale = begin
_pipe = (10 * precision(Divisor)),
_pipe@1 = erlang:float(_pipe),
_pipe@2 = gleam@float:divide(_pipe@1, 3.0),
_pipe@3 = gleam@result:lazy_unwrap(_pipe@2, fun() -> +0.0 end),
_pipe@4 = math:ceil(_pipe@3),
_pipe@5 = erlang:round(_pipe@4),
gleam@int:add(_pipe@5, precision(Dividend))
end,
_pipe@10 = case (scale(Divisor) - scale(Dividend)) + New_scale of
X when X > 0 ->
_pipe@6 = unscaled_value(Dividend),
_pipe@7 = multiply_power_of_ten(_pipe@6, X),
divide_and_round(
_pipe@7,
unscaled_value(Divisor),
New_scale,
Rounding
);
X@1 ->
_pipe@8 = unscaled_value(Divisor),
_pipe@9 = multiply_power_of_ten(_pipe@8, - X@1),
divide_and_round(
unscaled_value(Dividend),
_pipe@9,
New_scale,
Rounding
)
end,
trim_zeros_to_match_scale(_pipe@10, Preferred_scale).
-file("src/bigdecimal.gleam", 335).
?DOC(
" Divide the dividend by the divisor.\n"
" The result has a preferred scale of `scale(dividend) - scale(divisor)`,\n"
" but might have scale up to `precision(dividend) + ceil(10 * precision(divisor) / 3)`.\n"
).
-spec divide(big_decimal(), big_decimal(), bigdecimal@rounding:rounding_mode()) -> big_decimal().
divide(Dividend, Divisor, Rounding) ->
New_scale = scale(Dividend) - scale(Divisor),
case {signum(Dividend), signum(Divisor)} of
{_, 0} ->
zero();
{0, _} ->
{big_decimal, bigi_ffi:from(0), New_scale};
{_, _} ->
divide_internal(Dividend, Divisor, New_scale, Rounding)
end.
-file("src/bigdecimal.gleam", 441).
?DOC(
" Computes the **truncating remainder** of two `BigDecimal` values.\n"
"\n"
" The sign of the result always matches the sign of `value`\n"
" (the dividend), and the remainder may be negative.\n"
"\n"
" Follows the standard Gleam divide-by-zero rule of 0 when the divisor is 0.\n"
"\n"
" Note: This is **not** a modulo operation.\n"
).
-spec remainder(big_decimal(), big_decimal()) -> big_decimal().
remainder(Value, Divisor) ->
Common_scale = gleam@int:max(scale(Value), scale(Divisor)),
_pipe@2 = bigi_ffi:remainder(
begin
_pipe = rescale(Value, Common_scale, floor),
unscaled_value(_pipe)
end,
begin
_pipe@1 = rescale(Divisor, Common_scale, floor),
unscaled_value(_pipe@1)
end
),
{big_decimal, _pipe@2, Common_scale}.
-file("src/bigdecimal.gleam", 455).
?DOC(
" Returns an error if the exponent is negative.\n"
" (Inherited behaviour from `bigi`)\n"
).
-spec power(big_decimal(), integer()) -> {ok, big_decimal()} | {error, nil}.
power(Value, Exponent) ->
_pipe = unscaled_value(Value),
_pipe@1 = bigi_ffi:power(_pipe, bigi_ffi:from(Exponent)),
gleam@result:map(
_pipe@1,
fun(_capture) ->
{big_decimal, _capture, gleam@int:multiply(scale(Value), Exponent)}
end
).
-file("src/bigdecimal.gleam", 495).
-spec parse_unscaled(binary(), integer()) -> {ok, big_decimal()} | {error, nil}.
parse_unscaled(Value, Scale) ->
_pipe = bigi_ffi:from_string(Value),
gleam@result:map(_pipe, fun(_capture) -> {big_decimal, _capture, Scale} end).
-file("src/bigdecimal.gleam", 486).
-spec parse_decimal(binary(), integer()) -> {ok, big_decimal()} | {error, nil}.
parse_decimal(Value, Initial_scale) ->
case begin
_pipe = Value,
gleam@string:split_once(_pipe, <<"."/utf8>>)
end of
{ok, {Before, After}} ->
parse_unscaled(
<<Before/binary, After/binary>>,
erlang:byte_size(After) + Initial_scale
);
{error, _} ->
parse_unscaled(Value, Initial_scale)
end.
-file("src/bigdecimal.gleam", 474).
-spec parse_exponential(binary()) -> {ok, big_decimal()} | {error, nil}.
parse_exponential(Value) ->
Value@1 = begin
_pipe = Value,
_pipe@1 = gleam@string:trim(_pipe),
string:lowercase(_pipe@1)
end,
case begin
_pipe@2 = Value@1,
gleam@string:split_once(_pipe@2, <<"e"/utf8>>)
end of
{ok, {Number, Exponent}} ->
_pipe@3 = gleam_stdlib:parse_int(Exponent),
_pipe@4 = gleam@result:map(_pipe@3, fun gleam@int:negate/1),
gleam@result:'try'(
_pipe@4,
fun(_capture) -> parse_decimal(Number, _capture) end
);
{error, _} ->
parse_decimal(Value@1, 0)
end.
-file("src/bigdecimal.gleam", 470).
-spec from_string(binary()) -> {ok, big_decimal()} | {error, nil}.
from_string(Value) ->
parse_exponential(Value).
-file("src/bigdecimal.gleam", 461).
-spec from_float(float()) -> big_decimal().
from_float(Value) ->
Bigd@1 = case begin
_pipe = gleam_stdlib:float_to_string(Value),
from_string(_pipe)
end of
{ok, Bigd} -> Bigd;
_assert_fail ->
erlang:error(#{gleam_error => let_assert,
message => <<"Pattern match failed, no pattern matched the value."/utf8>>,
file => <<?FILEPATH/utf8>>,
module => <<"bigdecimal"/utf8>>,
function => <<"from_float"/utf8>>,
line => 463,
value => _assert_fail,
start => 12125,
'end' => 12192,
pattern_start => 12136,
pattern_end => 12144})
end,
Bigd@1.
-file("src/bigdecimal.gleam", 508).
?DOC(
" Converts a BigDecimal into a plain (non-scientific) decimal string.\n"
"\n"
" This function returns a **lossless** string representation of the number:\n"
"\n"
" - The number’s **scale is preserved**\n"
" - Trailing zeros are **not trimmed**\n"
" - The result can be parsed back to the same exact BigDecimal\n"
).
-spec to_plain_string(big_decimal()) -> binary().
to_plain_string(Value) ->
Scale = scale(Value),
Unscaled_abs = begin
_pipe = unscaled_value(Value),
_pipe@1 = erlang:abs(_pipe),
erlang:integer_to_binary(_pipe@1)
end,
String_builder = case compare_to_zero(Value) of
lt ->
gleam_stdlib:identity(<<"-"/utf8>>);
_ ->
gleam@string_tree:new()
end,
Integer_part_end_zeros = gleam@string:repeat(<<"0"/utf8>>, - Scale),
Integer_part_value = gleam@string:drop_end(Unscaled_abs, Scale),
String_builder@1 = case Integer_part_value of
<<""/utf8>> ->
gleam@string_tree:append(String_builder, <<"0"/utf8>>);
<<"0"/utf8>> ->
gleam@string_tree:append(String_builder, <<"0"/utf8>>);
_ ->
_pipe@2 = gleam@string_tree:append(
String_builder,
Integer_part_value
),
gleam@string_tree:append(_pipe@2, Integer_part_end_zeros)
end,
Digits = erlang:byte_size(Unscaled_abs),
Fractional_part_start_zeros = gleam@string:repeat(
<<"0"/utf8>>,
Scale - Digits
),
Fractional_part_digits = gleam@int:min(Digits, gleam@int:max(0, Scale)),
Fractional_part_value = gleam@string:slice(
Unscaled_abs,
- Fractional_part_digits,
Fractional_part_digits
),
String_builder@2 = case Fractional_part_value of
<<""/utf8>> ->
String_builder@1;
_ ->
_pipe@3 = gleam@string_tree:append(String_builder@1, <<"."/utf8>>),
_pipe@4 = gleam@string_tree:append(
_pipe@3,
Fractional_part_start_zeros
),
gleam@string_tree:append(_pipe@4, Fractional_part_value)
end,
unicode:characters_to_binary(String_builder@2).