Sign Up
Log In
Log In
or
Sign Up
Places
All Projects
Status Monitor
Collapse sidebar
home:Ledest:erlang:23
erlang
2681-Change-io_lib_format-fwrite_g-1-to-use-Ryu...
Overview
Repositories
Revisions
Requests
Users
Attributes
Meta
File 2681-Change-io_lib_format-fwrite_g-1-to-use-Ryu.patch of Package erlang
From c7614bca940da8f05884f08af883c2ef131e0250 Mon Sep 17 00:00:00 2001 From: Thomas Depierre <depierre.thomas@gmail.com> Date: Mon, 21 Dec 2020 16:11:20 +0100 Subject: [PATCH] Change io_lib_format:fwrite_g/1 to use Ryu io_lib_format_fwrite_g/1 now use the Ryu algorithm, see (https://dl.acm.org/doi/pdf/10.1145/3192366.3192369). We get an approximately 3x speedup over the whole doubles, with a more stable performance profile. The Dragon4 implementation used before had a performance profile linear with the size of the double to print. We also see a 10% reduction in memory use with Ryu over the old algorithm. It is worth noting that this implementation is slightly slower (10% to 30%) for "small" doubles in some cases. This commit does not try to optimise this case yet. The Ryu algorithm depends on a lookup table that is generated upfront. This commit add a script to generate it (mostly in case a bug is found in it or we decide to change the size of the lookup table) and the output of said script in io_lib_format_ryu_table.erl. This is done because the table do not change from a build to another and should not be regenerated outside of a bug or a fundamental change in the algorithm. The Ryu algorithm has a know worst case scenario for doubles that can be represented as "small" integer. This commit introduce a optimised handling for this case. --- lib/stdlib/scripts/generate_ryu_table.escript | 108 +++ lib/stdlib/src/Makefile | 1 + lib/stdlib/src/io_lib_format.erl | 382 ++++++---- lib/stdlib/src/io_lib_format_ryu_table.erl | 686 ++++++++++++++++++ lib/stdlib/src/stdlib.app.src | 1 + lib/stdlib/test/io_SUITE.erl | 192 ++++- 6 files changed, 1206 insertions(+), 164 deletions(-) create mode 100755 lib/stdlib/scripts/generate_ryu_table.escript create mode 100644 lib/stdlib/src/io_lib_format_ryu_table.erl diff --git a/lib/stdlib/scripts/generate_ryu_table.escript b/lib/stdlib/scripts/generate_ryu_table.escript new file mode 100755 index 0000000000..7191b64cd3 --- /dev/null +++ b/lib/stdlib/scripts/generate_ryu_table.escript @@ -0,0 +1,108 @@ +#!/usr/bin/env escript +%% -*- erlang -*- +%%! +A0 +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 2017-2019. All Rights Reserved. +%% +%% Licensed under the Apache License, Version 2.0 (the "License"); +%% you may not use this file except in compliance with the License. +%% You may obtain a copy of the License at +%% +%% http://www.apache.org/licenses/LICENSE-2.0 +%% +%% Unless required by applicable law or agreed to in writing, software +%% distributed under the License is distributed on an "AS IS" BASIS, +%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +%% See the License for the specific language governing permissions and +%% limitations under the License. +%% +%% %CopyrightEnd% +%% + +-mode(compile). + +-define(MOD, "io_lib_format_ryu_table"). + +-define(TABLE_SIZE, 326). +-define(INV_TABLE_SIZE, 342). + +-define(POW5_BITCOUNT, 125). +-define(POW5_INV_BITCOUNT, 125). + +main(_) -> + Values = [ values(X) || X <- lists:seq(0, ?TABLE_SIZE - 1)], + InvValues = [ inv_values(X) || X <- lists:seq(0, ?INV_TABLE_SIZE - 1)], + + %% Make module + {ok, Out} = file:open("../src/" ++ ?MOD ++ ".erl", [write]), + gen_file(Out, Values, InvValues), + ok = file:close(Out), + ok. + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +inv_values(X) -> + Pow = pow5(X), + Pow5len = log2floor(Pow), + J = Pow5len + ?POW5_INV_BITCOUNT - 1, + Inv = ((1 bsl J) div Pow) + 1, + {X, Inv}. + +values(X) -> + Pow = pow5(X), + Pow5len = log2floor(Pow), + Pow5 = Pow bsr (Pow5len - ?POW5_BITCOUNT), + {X, Pow5}. + +pow5(0) -> + 1; +pow5(1) -> + 5; +pow5(X) -> + 5 * pow5(X - 1). + +log2floor(Int) when is_integer(Int), Int > 0 -> + log2floor(Int, 0). + +log2floor(0, N) -> + N; +log2floor(Int, N) -> + log2floor(Int bsr 1, 1 + N). + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +gen_file(Fd, Values, InvValues) -> + gen_header(Fd), + gen_pow5_static(Fd), + gen_table(Fd, Values), + gen_inv_table(Fd, InvValues), + ok. + +gen_header(Fd) -> + io:put_chars(Fd, "%%\n%% this file is generated do not modify\n"), + io:put_chars(Fd, "%% see ../script/generate_ryu_table.escript\n\n"), + io:put_chars(Fd, "-module(" ++ ?MOD ++").\n"), + io:put_chars(Fd, "-export([pow5_bitcount/0, pow5_inv_bitcount/0, value/1, inv_value/1]).\n\n"), + ok. + +gen_pow5_static(Fd) -> + io:put_chars(Fd, "-spec pow5_bitcount() -> integer().\n"), + io:format(Fd, "pow5_bitcount() -> ~p.~n~n", [?POW5_BITCOUNT]), + io:put_chars(Fd, "-spec pow5_inv_bitcount() -> integer().\n"), + io:format(Fd, "pow5_inv_bitcount() -> ~p.~n~n", [?POW5_INV_BITCOUNT]), + ok. + +gen_table(Fd, Values) -> + io:put_chars(Fd, "-spec value(integer()) -> integer().\n"), + [io:format(Fd, "value(~p) -> ~p;~n", [Key, Val]) || {Key,Val} <- Values], + io:put_chars(Fd, "value(_) -> error(function_clause).\n\n"), + ok. + +gen_inv_table(Fd, Values) -> + io:put_chars(Fd, "-spec inv_value(integer()) -> integer().\n"), + [io:format(Fd, "inv_value(~p) -> ~p;~n", [Key, Val]) || {Key,Val} <- Values], + io:put_chars(Fd, "inv_value(_) -> error(function_clause).\n"), + ok. + diff --git a/lib/stdlib/src/Makefile b/lib/stdlib/src/Makefile index 8a45b8e249..509648cb2b 100644 --- a/lib/stdlib/src/Makefile +++ b/lib/stdlib/src/Makefile @@ -91,6 +91,7 @@ MODULES= \ io \ io_lib \ io_lib_format \ + io_lib_format_ryu_table \ io_lib_fread \ io_lib_pretty \ lists \ diff --git a/lib/stdlib/src/io_lib_format.erl b/lib/stdlib/src/io_lib_format.erl index bf6869a492..9fab476750 100644 --- a/lib/stdlib/src/io_lib_format.erl +++ b/lib/stdlib/src/io_lib_format.erl @@ -550,183 +550,257 @@ float_data([_|Cs], Ds) -> %% float(1 bsl 53) is chosen as cutoff point. %% %% The algorithm that is used to find the decimal number that is -%% represented by the returned String is described in "Printing -%% Floating-Point Numbers Quickly and Accurately" in Proceedings of -%% the SIGPLAN '96 Conference on Programming Language Design and -%% Implementation. +%% represented by the returned String is described in "Ryu: Fast +%% Float-to-String Conversion" in Proceedings of 39th ACM SIGPLAN +%% Conference on Programming Language Design and Implementation. +%% https://dl.acm.org/doi/pdf/10.1145/3192366.3192369 -spec fwrite_g(float()) -> string(). - -fwrite_g(Fl) -> - signbit(Fl) ++ abs_fwrite_g(abs(Fl)). - -abs_fwrite_g(0.0) -> - "0.0"; -abs_fwrite_g(Float) when is_float(Float) -> - {Frac, Exp} = mantissa_exponent(Float), - {Place, Digits} = fwrite_g_1(Float, Exp, Frac), - insert_decimal(Place, [$0 + D || D <- Digits], Float). - --define(BIG_POW, (1 bsl 52)). --define(MIN_EXP, (-1074)). - -mantissa_exponent(F) -> - case <<F:64/float>> of - <<_S:1, 0:11, M:52>> -> % denormalized - E = log2floor(M), - {M bsl (53 - E), E - 52 - 1075}; - <<_S:1, BE:11, M:52>> when BE < 2047 -> - {M + ?BIG_POW, BE - 1075} +fwrite_g(Float) -> + case sign_mantissa_exponent(Float) of + {0, 0, 0} -> "0.0"; + {1, 0, 0} -> "-0.0"; + {S, M, E} when E < 2047 -> + {Place, Digits} = + case is_small_int(M, E) of + {int, M1, E1} -> + compute_shortest_int(M1, E1); + not_int -> + fwrite_g_1(M, E) + end, + DigitList = insert_decimal(Place, Digits, Float), + insert_minus(S, DigitList) end. -fwrite_g_1(Float, Exp, Frac) -> - Round = (Frac band 1) =:= 0, - if - Exp >= 0 -> - BExp = 1 bsl Exp, - if - Frac =:= ?BIG_POW -> - scale(Frac * BExp * 4, 4, BExp * 2, BExp, - Round, Round, Float); - true -> - scale(Frac * BExp * 2, 2, BExp, BExp, - Round, Round, Float) - end; - Exp < ?MIN_EXP -> - BExp = 1 bsl (?MIN_EXP - Exp), - scale(Frac * 2, 1 bsl (1 - Exp), BExp, BExp, - Round, Round, Float); - Exp > ?MIN_EXP, Frac =:= ?BIG_POW -> - scale(Frac * 4, 1 bsl (2 - Exp), 2, 1, - Round, Round, Float); - true -> - scale(Frac * 2, 1 bsl (1 - Exp), 1, 1, - Round, Round, Float) - end. +-define(BIG_POW, (1 bsl 52)). +-define(DECODE_CORRECTION, 1075). -scale(R, S, MPlus, MMinus, LowOk, HighOk, Float) -> - Est = int_ceil(math:log10(abs(Float)) - 1.0e-10), - %% Note that the scheme implementation uses a 326 element look-up - %% table for int_pow(10, N) where we do not. - if - Est >= 0 -> - fixup(R, S * int_pow(10, Est), MPlus, MMinus, Est, - LowOk, HighOk); - true -> - Scale = int_pow(10, -Est), - fixup(R * Scale, S, MPlus * Scale, MMinus * Scale, Est, - LowOk, HighOk) - end. +sign_mantissa_exponent(F) -> + <<S:1, BE:11, M:52>> = <<F:64/float>>, + {S, M , BE}. -fixup(R, S, MPlus, MMinus, K, LowOk, HighOk) -> - TooLow = if - HighOk -> R + MPlus >= S; - true -> R + MPlus > S - end, - case TooLow of +is_small_int(M, E) -> + M2 = ?BIG_POW bor M, + E2 = E - ?DECODE_CORRECTION, + case E2 > 0 orelse E2 < -52 of true -> - {K + 1, generate(R, S, MPlus, MMinus, LowOk, HighOk)}; - false -> - {K, generate(R * 10, S, MPlus * 10, MMinus * 10, LowOk, HighOk)} + %% f = m2 * 2^e2 >= 2^53 is an integer. + %% Ignore this case for now. + %% or f < 1 + not_int; + _ -> + %% Since 2^52 <= m2 < 2^53 and 0 <= -e2 <= 52: 1 <= f = m2 / 2^-e2 < 2^53. + %% Test if the lower -e2 bits of the significand are 0, i.e. whether the fraction is 0. + Mask = (1 bsl -E2) - 1, + Fraction = M2 band Mask, + case Fraction of + 0 -> + %% f is an integer in the range [1, 2^53). + %% Note: mantissa might contain trailing (decimal) 0's. + {int, M2 bsr -E2, 0}; + _ -> + not_int + end end. -generate(R0, S, MPlus, MMinus, LowOk, HighOk) -> - D = R0 div S, - R = R0 rem S, - TC1 = if - LowOk -> R =< MMinus; - true -> R < MMinus - end, - TC2 = if - HighOk -> R + MPlus >= S; - true -> R + MPlus > S - end, - case {TC1, TC2} of - {false, false} -> - [D | generate(R * 10, S, MPlus * 10, MMinus * 10, LowOk, HighOk)]; - {false, true} -> - [D + 1]; - {true, false} -> - [D]; - {true, true} when R * 2 < S -> - [D]; - {true, true} -> - [D + 1] - end. +%% For small integers in the range [1, 2^53), v.mantissa might contain trailing (decimal) zeros. +compute_shortest_int(M, E) when M rem 10 =:= 0 -> + Q = M div 10, + compute_shortest_int(Q, E + 1); +compute_shortest_int(M, E) -> + {E, integer_to_list(M)}. + +fwrite_g_1(M, E) -> + {Mf, Ef} = decode(M, E), + Shift = mmshift(M, E), + Mv = 4 * Mf, + {Q, Vm, Vr, Vp, E10} = convert_to_decimal(Ef, Mv, Shift), + Accept = M rem 2 == 0, + {VmIsTrailingZero, VrIsTrailingZero, Vp1} = bounds(Mv, Q, Vp, Accept, Ef, Shift), + {D1, E1} = compute_shortest(Vm, Vr, Vp1, VmIsTrailingZero, VrIsTrailingZero, Accept), + {E1 + E10, integer_to_list(D1)}. + +decode(Mantissa, 0) -> + {Mantissa, 1 - ?DECODE_CORRECTION - 2}; +decode(Mantissa, Exponent) -> + {Mantissa + ?BIG_POW, Exponent - ?DECODE_CORRECTION - 2}. + +mmshift(0, E) when E > 1 -> + 0; +mmshift(_M, _E) -> + 1. + +convert_to_decimal(E2, Mv, Shift) when E2 >= 0 -> + Q = max(0, ((E2 * 78913) bsr 18) - 1), + Mul = io_lib_format_ryu_table:inv_value(Q), + K = io_lib_format_ryu_table:pow5_inv_bitcount() + pow5bits(Q) - 1, + I = -E2 + Q + K, + {Vm, Vr, Vp} = mulShiftAll(Mv, Shift, I, Mul), + {Q, Vm, Vr, Vp, Q}; + +convert_to_decimal(E2, Mv, Shift) when E2 < 0 -> + Q = max(0, ((-E2 * 732923) bsr 20) - 1), + I = -E2 - Q, + K = pow5bits(I) - io_lib_format_ryu_table:pow5_bitcount(), + From_file = io_lib_format_ryu_table:value(I), + J = Q - K, + {Vm, Vr, Vp} = mulShiftAll(Mv, Shift, J, From_file), + E10 = E2 + Q, + {Q, Vm, Vr, Vp, E10}. + +pow5bits(E) -> + ((E * 1217359) bsr 19) + 1. + +mulShiftAll(Mv, Shift, J, Mul) -> + A = mulShift64(Mv - 1 - Shift, Mul, J), + B = mulShift64(Mv, Mul, J), + C = mulShift64(Mv + 2,Mul, J), + {A, B, C}. + +mulShift64(M, Mul, J) -> + (M * Mul) bsr J. + +bounds(Mv, Q, Vp, _Accept, E2, _Shift) when E2 >= 0, Q =< 21, Mv rem 5 =:= 0 -> + {false, multipleOfPowerOf5(Mv, Q) , Vp}; +bounds(Mv, Q, Vp, true, E2, Shift) when E2 >= 0, Q =< 21 -> + {multipleOfPowerOf5(Mv - 1 - Shift, Q), false , Vp}; +bounds(Mv, Q, Vp, _Accept, E2, _Shift) when E2 >= 0, Q =< 21 -> + {false, false , Vp - vpmodifier(multipleOfPowerOf5(Mv + 2, Q))}; +bounds(_Mv, Q, Vp, true, E2, Shift) when E2 < 0, Q =< 1 -> + {Shift =:= 1, true, Vp}; +bounds(_Mv, Q, Vp, false, E2, _Shift) when E2 < 0, Q =< 1 -> + {false, true, Vp - 1}; +bounds(Mv, Q, Vp, _Accept, E2, _Shift) when E2 < 0, Q < 63 -> + {false, (Mv band ((1 bsl Q) -1 )) =:= 0, Vp}; +bounds(_Mv, _Q, Vp, _Accept, _E2, _Shift) -> + {false, false, Vp}. + +multipleOfPowerOf5(Value, Q) -> + pow5factor(Value) >= Q. + +pow5factor(Val) -> + pow5factor(Val div 5, 0). + +pow5factor(Val, Count) when (Val rem 5) /= 0-> + Count; +pow5factor(Val, Count) -> + pow5factor(Val div 5, Count + 1). + +vpmodifier(true) -> + 1; +vpmodifier(false) -> + 0. + +compute_shortest(Vm, Vr, Vp, false, false, _Accept) -> + {Vm1, Vr1, Removed, RoundUp} = + general_case(Vm, Vr, Vp, 0, false), + Output = Vr1 + handle_normal_output_mod(Vr1, Vm1, RoundUp), + {Output, Removed}; +compute_shortest(Vm, Vr, Vp, VmIsTrailingZero, VrIsTrailingZero, Accept) -> + {Vm1, Vr1, Removed, LastRemovedDigit} = + handle_trailing_zeros(Vm, Vr, Vp, VmIsTrailingZero, VrIsTrailingZero, 0, 0), + Output = Vr1 + handle_zero_output_mod(Vr1, Vm1, Accept, VmIsTrailingZero, LastRemovedDigit), + {Output, Removed}. + +general_case(Vm, Vr, Vp, Removed, RoundUp) when (Vp div 100) =< (Vm div 100)-> + general_case_10(Vm, Vr, Vp, Removed, RoundUp); +general_case(Vm, Vr, Vp, Removed, _RU) -> + VmD100 = Vm div 100, + VrD100 = Vr div 100, + VpD100 = Vp div 100, + RoundUp = ((Vr rem 100) >= 50), + general_case_10(VmD100, VrD100, VpD100, 2 + Removed, RoundUp). + +general_case_10(Vm, Vr, Vp, Removed, RoundUp) + when (Vp div 10) =< (Vm div 10)-> + {Vm, Vr, Removed, RoundUp}; +general_case_10(Vm, Vr, Vp, Removed, _RU) -> + VmD10 = Vm div 10, + VrD10 = Vr div 10, + VpD10 = Vp div 10, + RoundUp = ((Vr rem 10) >= 5), + general_case_10(VmD10, VrD10, VpD10, 1 + Removed, RoundUp). + +handle_normal_output_mod(Vr, Vm, RoundUp) when (Vm =:= Vr) or RoundUp -> + 1; +handle_normal_output_mod(_Vr, _Vm, _RoundUp) -> + 0. + +handle_trailing_zeros(Vm, Vr, Vp, VmTZ, VrTZ, Removed, LastRemovedDigit) + when (Vp div 10) =< (Vm div 10)-> + vmIsTrailingZero(Vm, Vr, Vp, VmTZ, VrTZ, Removed, LastRemovedDigit); +handle_trailing_zeros(Vm, Vr, Vp, VmIsTrailingZero, VrIsTrailingZero, Removed, LastRemovedDigit) -> + VmTZ = VmIsTrailingZero and ((Vm rem 10) =:= 0), + VrTZ = VrIsTrailingZero and (LastRemovedDigit =:= 0), + handle_trailing_zeros(Vm div 10, Vr div 10, Vp div 10, VmTZ, VrTZ, 1 + Removed, Vr rem 10). + +vmIsTrailingZero(Vm, Vr, _Vp, false = _VmTZ, VrTZ, Removed, LastRemovedDigit) -> + handle_50_dotdot_0(Vm, Vr, VrTZ, Removed, LastRemovedDigit); +vmIsTrailingZero(Vm, Vr, _Vp, _VmTZ, VrTZ, Removed, LastRemovedDigit) when (Vm rem 10) /= 0 -> + handle_50_dotdot_0(Vm, Vr, VrTZ, Removed, LastRemovedDigit); +vmIsTrailingZero(Vm, Vr, Vp, VmTZ, VrTZ, Removed, LastRemovedDigit) -> + vmIsTrailingZero(Vm div 10, Vr div 10, Vp div 10, VmTZ, LastRemovedDigit == 0 andalso VrTZ, 1 + Removed, Vr rem 10). + +handle_50_dotdot_0(Vm, Vr, true, Removed, 5) when (Vr rem 2) =:= 0 -> + {Vm, Vr, Removed, 4}; +handle_50_dotdot_0(Vm, Vr, _VrTZ, Removed, LastRemovedDigit) -> + {Vm, Vr, Removed, LastRemovedDigit}. + +handle_zero_output_mod(_Vr, _Vm, _Accept, _VmTZ, LastRemovedDigit) when LastRemovedDigit >= 5 -> + 1; +handle_zero_output_mod(Vr, Vm, Accept, VmTZ, _LastRemovedDigit) when Vr =:= Vm, ((not Accept) or (not VmTZ)) -> + 1; +handle_zero_output_mod(_Vr, _Vm, _Accept, _VmTZ, _LastRemovedDigit) -> + 0. -insert_decimal(0, S, _) -> - "0." ++ S; insert_decimal(Place, S, Float) -> L = length(S), + Exp = Place + L - 1, + ExpL = integer_to_list(Exp), + ExpCost = length(ExpL) + 2, if - Place < 0; - Place >= L -> - ExpL = integer_to_list(Place - 1), - ExpDot = if L =:= 1 -> 2; true -> 1 end, - ExpCost = length(ExpL) + 1 + ExpDot, - if - Place < 0 -> - if - 2 - Place =< ExpCost -> - "0." ++ lists:duplicate(-Place, $0) ++ S; - true -> - insert_exp(ExpL, S) - end; + Place < 0 -> + if + Exp >= 0 -> + {S0, S1} = lists:split(L + Place, S), + S0 ++ "." ++ S1; + 2 - Place - L =< ExpCost -> + %% All integers in the range [-2^53, 2^53] can + %% be stored without loss of precision in an + %% IEEE 754 64-bit double but 2^53+1 cannot be + %% stored in an IEEE 754 64-bit double without + %% loss of precision (float((1 bsl 53)+1) =:= + %% float(1 bsl 53)). It thus makes sense to + %% show floats that are >= 2^53 or <= -2^53 in + %% scientific notation to indicate that the + %% number is so large that there could be loss + %% in precion when adding or subtracting 1. + %% + %% https://stackoverflow.com/questions/1848700/biggest-integer-that-can-be-stored-in-a-double?answertab=votes#tab-top + "0." ++ lists:duplicate(-Place - L, $0) ++ S; true -> - if - %% All integers in the range [-2^53, 2^53] can - %% be stored without loss of precision in an - %% IEEE 754 64-bit double but 2^53+1 cannot be - %% stored in an IEEE 754 64-bit double without - %% loss of precision (float((1 bsl 53)+1) =:= - %% float(1 bsl 53)). It thus makes sense to - %% show floats that are >= 2^53 or <= -2^53 in - %% scientific notation to indicate that the - %% number is so large that there could be loss - %% in precion when adding or subtracting 1. - %% - %% https://stackoverflow.com/questions/1848700/biggest-integer-that-can-be-stored-in-a-double?answertab=votes#tab-top - Place - L + 2 =< ExpCost andalso abs(Float) < float(1 bsl 53) -> - S ++ lists:duplicate(Place - L, $0) ++ ".0"; - true -> - insert_exp(ExpL, S) - end + insert_exp(ExpL, S) end; true -> - {S0, S1} = lists:split(Place, S), - S0 ++ "." ++ S1 + Dot = if L =:= 1 -> 1; true -> 0 end, + if + ExpCost + Dot >= Place + 2 andalso abs(Float) < float(1 bsl 53) -> + S ++ lists:duplicate(Place, $0) ++ ".0"; + true -> + insert_exp(ExpL, S) + end end. + insert_exp(ExpL, [C]) -> [C] ++ ".0e" ++ ExpL; insert_exp(ExpL, [C | S]) -> [C] ++ "." ++ S ++ "e" ++ ExpL. -int_ceil(X) when is_float(X) -> - T = trunc(X), - case (X - T) of - Neg when Neg < 0 -> T; - Pos when Pos > 0 -> T + 1; - _ -> T - end. - -int_pow(X, 0) when is_integer(X) -> - 1; -int_pow(X, N) when is_integer(X), is_integer(N), N > 0 -> - int_pow(X, N, 1). - -int_pow(X, N, R) when N < 2 -> - R * X; -int_pow(X, N, R) -> - int_pow(X * X, N bsr 1, case N band 1 of 1 -> R * X; 0 -> R end). - -log2floor(Int) when is_integer(Int), Int > 0 -> - log2floor(Int, 0). - -log2floor(0, N) -> - N; -log2floor(Int, N) -> - log2floor(Int bsr 1, 1 + N). +insert_minus(0, Digits) -> + Digits; +insert_minus(1, Digits) -> + [$-] ++ Digits. %% fwrite_g(Float, Field, Adjust, Precision, PadChar) %% Use the f form if Float is >= 0.1 and < 1.0e4, diff --git a/lib/stdlib/src/io_lib_format_ryu_table.erl b/lib/stdlib/src/io_lib_format_ryu_table.erl new file mode 100644 index 0000000000..b20268a939 --- /dev/null +++ b/lib/stdlib/src/io_lib_format_ryu_table.erl @@ -0,0 +1,686 @@ +%% +%% this file is generated do not modify +%% see ../script/generate_ryu_table.escript + +-module(io_lib_format_ryu_table). +-export([pow5_bitcount/0, pow5_inv_bitcount/0, value/1, inv_value/1]). + +-spec pow5_bitcount() -> integer(). +pow5_bitcount() -> 125. + +-spec pow5_inv_bitcount() -> integer(). +pow5_inv_bitcount() -> 125. + +-spec value(integer()) -> integer(). +value(0) -> 21267647932558653966460912964485513216; +value(1) -> 26584559915698317458076141205606891520; +value(2) -> 33230699894622896822595176507008614400; +value(3) -> 41538374868278621028243970633760768000; +value(4) -> 25961484292674138142652481646100480000; +value(5) -> 32451855365842672678315602057625600000; +value(6) -> 40564819207303340847894502572032000000; +value(7) -> 25353012004564588029934064107520000000; +value(8) -> 31691265005705735037417580134400000000; +value(9) -> 39614081257132168796771975168000000000; +value(10) -> 24758800785707605497982484480000000000; +value(11) -> 30948500982134506872478105600000000000; +value(12) -> 38685626227668133590597632000000000000; +value(13) -> 24178516392292583494123520000000000000; +value(14) -> 30223145490365729367654400000000000000; +value(15) -> 37778931862957161709568000000000000000; +value(16) -> 23611832414348226068480000000000000000; +value(17) -> 29514790517935282585600000000000000000; +value(18) -> 36893488147419103232000000000000000000; +value(19) -> 23058430092136939520000000000000000000; +value(20) -> 28823037615171174400000000000000000000; +value(21) -> 36028797018963968000000000000000000000; +value(22) -> 22517998136852480000000000000000000000; +value(23) -> 28147497671065600000000000000000000000; +value(24) -> 35184372088832000000000000000000000000; +value(25) -> 21990232555520000000000000000000000000; +value(26) -> 27487790694400000000000000000000000000; +value(27) -> 34359738368000000000000000000000000000; +value(28) -> 21474836480000000000000000000000000000; +value(29) -> 26843545600000000000000000000000000000; +value(30) -> 33554432000000000000000000000000000000; +value(31) -> 41943040000000000000000000000000000000; +value(32) -> 26214400000000000000000000000000000000; +value(33) -> 32768000000000000000000000000000000000; +value(34) -> 40960000000000000000000000000000000000; +value(35) -> 25600000000000000000000000000000000000; +value(36) -> 32000000000000000000000000000000000000; +value(37) -> 40000000000000000000000000000000000000; +value(38) -> 25000000000000000000000000000000000000; +value(39) -> 31250000000000000000000000000000000000; +value(40) -> 39062500000000000000000000000000000000; +value(41) -> 24414062500000000000000000000000000000; +value(42) -> 30517578125000000000000000000000000000; +value(43) -> 38146972656250000000000000000000000000; +value(44) -> 23841857910156250000000000000000000000; +value(45) -> 29802322387695312500000000000000000000; +value(46) -> 37252902984619140625000000000000000000; +value(47) -> 23283064365386962890625000000000000000; +value(48) -> 29103830456733703613281250000000000000; +value(49) -> 36379788070917129516601562500000000000; +value(50) -> 22737367544323205947875976562500000000; +value(51) -> 28421709430404007434844970703125000000; +value(52) -> 35527136788005009293556213378906250000; +value(53) -> 22204460492503130808472633361816406250; +value(54) -> 27755575615628913510590791702270507812; +value(55) -> 34694469519536141888238489627838134765; +value(56) -> 21684043449710088680149056017398834228; +value(57) -> 27105054312137610850186320021748542785; +value(58) -> 33881317890172013562732900027185678482; +value(59) -> 42351647362715016953416125033982098102; +value(60) -> 26469779601696885595885078146238811314; +value(61) -> 33087224502121106994856347682798514142; +value(62) -> 41359030627651383743570434603498142678; +value(63) -> 25849394142282114839731521627186339173; +value(64) -> 32311742677852643549664402033982923967; +value(65) -> 40389678347315804437080502542478654959; +value(66) -> 25243548967072377773175314089049159349; +value(67) -> 31554436208840472216469142611311449186; +value(68) -> 39443045261050590270586428264139311483; +value(69) -> 24651903288156618919116517665087069677; +value(70) -> 30814879110195773648895647081358837096; +value(71) -> 38518598887744717061119558851698546370; +value(72) -> 24074124304840448163199724282311591481; +value(73) -> 30092655381050560203999655352889489352; +value(74) -> 37615819226313200254999569191111861690; +value(75) -> 23509887016445750159374730744444913556; +value(76) -> 29387358770557187699218413430556141945; +value(77) -> 36734198463196484624023016788195177431; +value(78) -> 22958874039497802890014385492621985894; +value(79) -> 28698592549372253612517981865777482368; +value(80) -> 35873240686715317015647477332221852960; +value(81) -> 22420775429197073134779673332638658100; +value(82) -> 28025969286496341418474591665798322625; +value(83) -> 35032461608120426773093239582247903282; +value(84) -> 21895288505075266733183274738904939551; +value(85) -> 27369110631344083416479093423631174439; +value(86) -> 34211388289180104270598866779538968048; +value(87) -> 21382117680737565169124291737211855030; +value(88) -> 26727647100921956461405364671514818788; +value(89) -> 33409558876152445576756705839393523485; +value(90) -> 41761948595190556970945882299241904356; +value(91) -> 26101217871994098106841176437026190222; +value(92) -> 32626522339992622633551470546282737778; +value(93) -> 40783152924990778291939338182853422223; +value(94) -> 25489470578119236432462086364283388889; +value(95) -> 31861838222649045540577607955354236111; +value(96) -> 39827297778311306925722009944192795139; +value(97) -> 24892061111444566828576256215120496962; +value(98) -> 31115076389305708535720320268900621202; +value(99) -> 38893845486632135669650400336125776503; +value(100) -> 24308653429145084793531500210078610314; +value(101) -> 30385816786431355991914375262598262893; +value(102) -> 37982270983039194989892969078247828616; +value(103) -> 23738919364399496868683105673904892885; +value(104) -> 29673649205499371085853882092381116106; +value(105) -> 37092061506874213857317352615476395133; +value(106) -> 23182538441796383660823345384672746958; +value(107) -> 28978173052245479576029181730840933698; +value(108) -> 36222716315306849470036477163551167122; +value(109) -> 22639197697066780918772798227219479451; +value(110) -> 28298997121333476148465997784024349314; +value(111) -> 35373746401666845185582497230030436643; +value(112) -> 22108591501041778240989060768769022902; +value(113) -> 27635739376302222801236325960961278627; +value(114) -> 34544674220377778501545407451201598284; +value(115) -> 21590421387736111563465879657000998927; +value(116) -> 26988026734670139454332349571251248659; +value(117) -> 33735033418337674317915436964064060824; +value(118) -> 42168791772922092897394296205080076030; +value(119) -> 26355494858076308060871435128175047519; +value(120) -> 32944368572595385076089293910218809399; +value(121) -> 41180460715744231345111617387773511748; +value(122) -> 25737787947340144590694760867358444843; +value(123) -> 32172234934175180738368451084198056053; +value(124) -> 40215293667718975922960563855247570067; +value(125) -> 25134558542324359951850352409529731292; +value(126) -> 31418198177905449939812940511912164115; +value(127) -> 39272747722381812424766175639890205143; +value(128) -> 24545467326488632765478859774931378214; +value(129) -> 30681834158110790956848574718664222768; +value(130) -> 38352292697638488696060718398330278460; +value(131) -> 23970182936024055435037948998956424037; +value(132) -> 29962728670030069293797436248695530047; +value(133) -> 37453410837537586617246795310869412559; +value(134) -> 23408381773460991635779247069293382849; +value(135) -> 29260477216826239544724058836616728561; +value(136) -> 36575596521032799430905073545770910702; +value(137) -> 22859747825645499644315670966106819189; +value(138) -> 28574684782056874555394588707633523986; +value(139) -> 35718355977571093194243235884541904982; +value(140) -> 22323972485981933246402022427838690614; +value(141) -> 27904965607477416558002528034798363267; +value(142) -> 34881207009346770697503160043497954084; +value(143) -> 21800754380841731685939475027186221303; +value(144) -> 27250942976052164607424343783982776628; +value(145) -> 34063678720065205759280429729978470785; +value(146) -> 21289799200040753599550268581236544241; +value(147) -> 26612249000050941999437835726545680301; +value(148) -> 33265311250063677499297294658182100376; +value(149) -> 41581639062579596874121618322727625471; +value(150) -> 25988524414112248046326011451704765919; +value(151) -> 32485655517640310057907514314630957399; +value(152) -> 40607069397050387572384392893288696749; +value(153) -> 25379418373156492232740245558305435468; +value(154) -> 31724272966445615290925306947881794335; +value(155) -> 39655341208057019113656633684852242919; +value(156) -> 24784588255035636946035396053032651824; +value(157) -> 30980735318794546182544245066290814780; +value(158) -> 38725919148493182728180306332863518475; +value(159) -> 24203699467808239205112691458039699047; +value(160) -> 30254624334760299006390864322549623809; +value(161) -> 37818280418450373757988580403187029761; +value(162) -> 23636425261531483598742862751991893600; +value(163) -> 29545531576914354498428578439989867001; +value(164) -> 36931914471142943123035723049987333751; +value(165) -> 23082446544464339451897326906242083594; +value(166) -> 28853058180580424314871658632802604493; +value(167) -> 36066322725725530393589573291003255616; +value(168) -> 22541451703578456495993483306877034760; +value(169) -> 28176814629473070619991854133596293450; +value(170) -> 35221018286841338274989817666995366813; +value(171) -> 22013136429275836421868636041872104258; +value(172) -> 27516420536594795527335795052340130322; +value(173) -> 34395525670743494409169743815425162903; +value(174) -> 21497203544214684005731089884640726814; +value(175) -> 26871504430268355007163862355800908518; +value(176) -> 33589380537835443758954827944751135647; +value(177) -> 41986725672294304698693534930938919559; +value(178) -> 26241703545183940436683459331836824724; +value(179) -> 32802129431479925545854324164796030906; +value(180) -> 41002661789349906932317905205995038632; +value(181) -> 25626663618343691832698690753746899145; +value(182) -> 32033329522929614790873363442183623931; +value(183) -> 40041661903662018488591704302729529914; +value(184) -> 25026038689788761555369815189205956196; +value(185) -> 31282548362235951944212268986507445245; +value(186) -> 39103185452794939930265336233134306557; +value(187) -> 24439490907996837456415835145708941598; +value(188) -> 30549363634996046820519793932136176997; +value(189) -> 38186704543745058525649742415170221247; +value(190) -> 23866690339840661578531089009481388279; +value(191) -> 29833362924800826973163861261851735349; +value(192) -> 37291703656001033716454826577314669186; +value(193) -> 23307314785000646072784266610821668241; +value(194) -> 29134143481250807590980333263527085302; +value(195) -> 36417679351563509488725416579408856627; +value(196) -> 22761049594727193430453385362130535392; +value(197) -> 28451311993408991788066731702663169240; +value(198) -> 35564139991761239735083414628328961550; +value(199) -> 22227587494850774834427134142705600969; +value(200) -> 27784484368563468543033917678382001211; +value(201) -> 34730605460704335678792397097977501514; +value(202) -> 21706628412940209799245248186235938446; +value(203) -> 27133285516175262249056560232794923058; +value(204) -> 33916606895219077811320700290993653822; +value(205) -> 42395758619023847264150875363742067278; +value(206) -> 26497349136889904540094297102338792048; +value(207) -> 33121686421112380675117871377923490061; +value(208) -> 41402108026390475843897339222404362576; +value(209) -> 25876317516494047402435837014002726610; +value(210) -> 32345396895617559253044796267503408262; +value(211) -> 40431746119521949066305995334379260328; +value(212) -> 25269841324701218166441247083987037705; +value(213) -> 31587301655876522708051558854983797131; +value(214) -> 39484127069845653385064448568729746414; +value(215) -> 24677579418653533365665280355456091509; +value(216) -> 30846974273316916707081600444320114386; +value(217) -> 38558717841646145883852000555400142982; +value(218) -> 24099198651028841177407500347125089364; +value(219) -> 30123998313786051471759375433906361705; +value(220) -> 37654997892232564339699219292382952131; +value(221) -> 23534373682645352712312012057739345082; +value(222) -> 29417967103306690890390015072174181352; +value(223) -> 36772458879133363612987518840217726691; +value(224) -> 22982786799458352258117199275136079181; +value(225) -> 28728483499322940322646499093920098977; +value(226) -> 35910604374153675403308123867400123721; +value(227) -> 22444127733846047127067577417125077326; +value(228) -> 28055159667307558908834471771406346657; +value(229) -> 35068949584134448636043089714257933322; +value(230) -> 21918093490084030397526931071411208326; +value(231) -> 27397616862605037996908663839264010407; +value(232) -> 34247021078256297496135829799080013009; +value(233) -> 21404388173910185935084893624425008131; +value(234) -> 26755485217387732418856117030531260163; +value(235) -> 33444356521734665523570146288164075204; +value(236) -> 41805445652168331904462682860205094006; +value(237) -> 26128403532605207440289176787628183753; +value(238) -> 32660504415756509300361470984535229692; +value(239) -> 40825630519695636625451838730669037115; +value(240) -> 25516019074809772890907399206668148197; +value(241) -> 31895023843512216113634249008335185246; +value(242) -> 39868779804390270142042811260418981558; +value(243) -> 24917987377743918838776757037761863473; +value(244) -> 31147484222179898548470946297202329342; +value(245) -> 38934355277724873185588682871502911677; +value(246) -> 24333972048578045740992926794689319798; +value(247) -> 30417465060722557176241158493361649748; +value(248) -> 38021831325903196470301448116702062185; +value(249) -> 23763644578689497793938405072938788865; +value(250) -> 29704555723361872242423006341173486082; +value(251) -> 37130694654202340303028757926466857602; +value(252) -> 23206684158876462689392973704041786001; +value(253) -> 29008355198595578361741217130052232502; +value(254) -> 36260443998244472952176521412565290627; +value(255) -> 22662777498902795595110325882853306642; +value(256) -> 28328471873628494493887907353566633302; +value(257) -> 35410589842035618117359884191958291628; +value(258) -> 22131618651272261323349927619973932267; +value(259) -> 27664523314090326654187409524967415334; +value(260) -> 34580654142612908317734261906209269168; +value(261) -> 21612908839133067698583913691380793230; +value(262) -> 27016136048916334623229892114225991537; +value(263) -> 33770170061145418279037365142782489422; +value(264) -> 42212712576431772848796706428478111778; +value(265) -> 26382945360269858030497941517798819861; +value(266) -> 32978681700337322538122426897248524826; +value(267) -> 41223352125421653172653033621560656033; +value(268) -> 25764595078388533232908146013475410020; +value(269) -> 32205743847985666541135182516844262526; +value(270) -> 40257179809982083176418978146055328157; +value(271) -> 25160737381238801985261861341284580098; +value(272) -> 31450921726548502481577326676605725123; +value(273) -> 39313652158185628101971658345757156403; +value(274) -> 24571032598866017563732286466098222752; +value(275) -> 30713790748582521954665358082622778440; +value(276) -> 38392238435728152443331697603278473050; +value(277) -> 23995149022330095277082311002049045656; +value(278) -> 29993936277912619096352888752561307070; +value(279) -> 37492420347390773870441110940701633838; +value(280) -> 23432762717119233669025694337938521149; +value(281) -> 29290953396399042086282117922423151436; +value(282) -> 36613691745498802607852647403028939295; +value(283) -> 22883557340936751629907904626893087059; +value(284) -> 28604446676170939537384880783616358824; +value(285) -> 35755558345213674421731100979520448530; +value(286) -> 22347223965758546513581938112200280331; +value(287) -> 27934029957198183141977422640250350414; +value(288) -> 34917537446497728927471778300312938018; +value(289) -> 21823460904061080579669861437695586261; +value(290) -> 27279326130076350724587326797119482826; +value(291) -> 34099157662595438405734158496399353533; +value(292) -> 21311973539122149003583849060249595958; +value(293) -> 26639966923902686254479811325311994947; +value(294) -> 33299958654878357818099764156639993684; +value(295) -> 41624948318597947272624705195799992106; +value(296) -> 26015592699123717045390440747374995066; +value(297) -> 32519490873904646306738050934218743833; +value(298) -> 40649363592380807883422563667773429791; +value(299) -> 25405852245238004927139102292358393619; +value(300) -> 31757315306547506158923877865447992024; +value(301) -> 39696644133184382698654847331809990030; +value(302) -> 24810402583240239186659279582381243769; +value(303) -> 31013003229050298983324099477976554711; +value(304) -> 38766254036312873729155124347470693389; +value(305) -> 24228908772695546080721952717169183368; +value(306) -> 30286135965869432600902440896461479210; +value(307) -> 37857669957336790751128051120576849012; +value(308) -> 23661043723335494219455031950360530633; +value(309) -> 29576304654169367774318789937950663291; +value(310) -> 36970380817711709717898487422438329114; +value(311) -> 23106488011069818573686554639023955696; +value(312) -> 28883110013837273217108193298779944620; +value(313) -> 36103887517296591521385241623474930775; +value(314) -> 22564929698310369700865776014671831734; +value(315) -> 28206162122887962126082220018339789668; +value(316) -> 35257702653609952657602775022924737085; +value(317) -> 22036064158506220411001734389327960678; +value(318) -> 27545080198132775513752167986659950848; +value(319) -> 34431350247665969392190209983324938560; +value(320) -> 21519593904791230870118881239578086600; +value(321) -> 26899492380989038587648601549472608250; +value(322) -> 33624365476236298234560751936840760312; +value(323) -> 42030456845295372793200939921050950390; +value(324) -> 26269035528309607995750587450656843994; +value(325) -> 32836294410387009994688234313321054992; +value(_) -> error(function_clause). + +-spec inv_value(integer()) -> integer(). +inv_value(0) -> 42535295865117307932921825928971026433; +inv_value(1) -> 34028236692093846346337460743176821146; +inv_value(2) -> 27222589353675077077069968594541456917; +inv_value(3) -> 21778071482940061661655974875633165534; +inv_value(4) -> 34844914372704098658649559801013064854; +inv_value(5) -> 27875931498163278926919647840810451883; +inv_value(6) -> 22300745198530623141535718272648361506; +inv_value(7) -> 35681192317648997026457149236237378410; +inv_value(8) -> 28544953854119197621165719388989902728; +inv_value(9) -> 22835963083295358096932575511191922183; +inv_value(10) -> 36537540933272572955092120817907075492; +inv_value(11) -> 29230032746618058364073696654325660394; +inv_value(12) -> 23384026197294446691258957323460528315; +inv_value(13) -> 37414441915671114706014331717536845304; +inv_value(14) -> 29931553532536891764811465374029476243; +inv_value(15) -> 23945242826029513411849172299223580995; +inv_value(16) -> 38312388521647221458958675678757729591; +inv_value(17) -> 30649910817317777167166940543006183673; +inv_value(18) -> 24519928653854221733733552434404946938; +inv_value(19) -> 39231885846166754773973683895047915101; +inv_value(20) -> 31385508676933403819178947116038332081; +inv_value(21) -> 25108406941546723055343157692830665665; +inv_value(22) -> 40173451106474756888549052308529065064; +inv_value(23) -> 32138760885179805510839241846823252051; +inv_value(24) -> 25711008708143844408671393477458601641; +inv_value(25) -> 41137613933030151053874229563933762625; +inv_value(26) -> 32910091146424120843099383651147010100; +inv_value(27) -> 26328072917139296674479506920917608080; +inv_value(28) -> 42124916667422874679167211073468172928; +inv_value(29) -> 33699933333938299743333768858774538343; +inv_value(30) -> 26959946667150639794667015087019630674; +inv_value(31) -> 21567957333720511835733612069615704539; +inv_value(32) -> 34508731733952818937173779311385127263; +inv_value(33) -> 27606985387162255149739023449108101810; +inv_value(34) -> 22085588309729804119791218759286481448; +inv_value(35) -> 35336941295567686591665950014858370317; +inv_value(36) -> 28269553036454149273332760011886696254; +inv_value(37) -> 22615642429163319418666208009509357003; +inv_value(38) -> 36185027886661311069865932815214971205; +inv_value(39) -> 28948022309329048855892746252171976964; +inv_value(40) -> 23158417847463239084714197001737581571; +inv_value(41) -> 37053468555941182535542715202780130514; +inv_value(42) -> 29642774844752946028434172162224104411; +inv_value(43) -> 23714219875802356822747337729779283529; +inv_value(44) -> 37942751801283770916395740367646853646; +inv_value(45) -> 30354201441027016733116592294117482917; +inv_value(46) -> 24283361152821613386493273835293986334; +inv_value(47) -> 38853377844514581418389238136470378133; +inv_value(48) -> 31082702275611665134711390509176302507; +inv_value(49) -> 24866161820489332107769112407341042006; +inv_value(50) -> 39785858912782931372430579851745667209; +inv_value(51) -> 31828687130226345097944463881396533767; +inv_value(52) -> 25462949704181076078355571105117227014; +inv_value(53) -> 40740719526689721725368913768187563222; +inv_value(54) -> 32592575621351777380295131014550050577; +inv_value(55) -> 26074060497081421904236104811640040462; +inv_value(56) -> 41718496795330275046777767698624064739; +inv_value(57) -> 33374797436264220037422214158899251791; +inv_value(58) -> 26699837949011376029937771327119401433; +inv_value(59) -> 21359870359209100823950217061695521147; +inv_value(60) -> 34175792574734561318320347298712833834; +inv_value(61) -> 27340634059787649054656277838970267067; +inv_value(62) -> 21872507247830119243725022271176213654; +inv_value(63) -> 34996011596528190789960035633881941846; +inv_value(64) -> 27996809277222552631968028507105553477; +inv_value(65) -> 22397447421778042105574422805684442782; +inv_value(66) -> 35835915874844867368919076489095108450; +inv_value(67) -> 28668732699875893895135261191276086760; +inv_value(68) -> 22934986159900715116108208953020869408; +inv_value(69) -> 36695977855841144185773134324833391053; +inv_value(70) -> 29356782284672915348618507459866712843; +inv_value(71) -> 23485425827738332278894805967893370274; +inv_value(72) -> 37576681324381331646231689548629392439; +inv_value(73) -> 30061345059505065316985351638903513951; +inv_value(74) -> 24049076047604052253588281311122811161; +inv_value(75) -> 38478521676166483605741250097796497857; +inv_value(76) -> 30782817340933186884593000078237198286; +inv_value(77) -> 24626253872746549507674400062589758629; +inv_value(78) -> 39402006196394479212279040100143613806; +inv_value(79) -> 31521604957115583369823232080114891045; +inv_value(80) -> 25217283965692466695858585664091912836; +inv_value(81) -> 40347654345107946713373737062547060537; +inv_value(82) -> 32278123476086357370698989650037648430; +inv_value(83) -> 25822498780869085896559191720030118744; +inv_value(84) -> 41315998049390537434494706752048189990; +inv_value(85) -> 33052798439512429947595765401638551992; +inv_value(86) -> 26442238751609943958076612321310841594; +inv_value(87) -> 42307582002575910332922579714097346550; +inv_value(88) -> 33846065602060728266338063771277877240; +inv_value(89) -> 27076852481648582613070451017022301792; +inv_value(90) -> 21661481985318866090456360813617841434; +inv_value(91) -> 34658371176510185744730177301788546293; +inv_value(92) -> 27726696941208148595784141841430837035; +inv_value(93) -> 22181357552966518876627313473144669628; +inv_value(94) -> 35490172084746430202603701557031471404; +inv_value(95) -> 28392137667797144162082961245625177124; +inv_value(96) -> 22713710134237715329666368996500141699; +inv_value(97) -> 36341936214780344527466190394400226718; +inv_value(98) -> 29073548971824275621972952315520181375; +inv_value(99) -> 23258839177459420497578361852416145100; +inv_value(100) -> 37214142683935072796125378963865832159; +inv_value(101) -> 29771314147148058236900303171092665728; +inv_value(102) -> 23817051317718446589520242536874132582; +inv_value(103) -> 38107282108349514543232388058998612131; +inv_value(104) -> 30485825686679611634585910447198889705; +inv_value(105) -> 24388660549343689307668728357759111764; +inv_value(106) -> 39021856878949902892269965372414578822; +inv_value(107) -> 31217485503159922313815972297931663058; +inv_value(108) -> 24973988402527937851052777838345330446; +inv_value(109) -> 39958381444044700561684444541352528714; +inv_value(110) -> 31966705155235760449347555633082022971; +inv_value(111) -> 25573364124188608359478044506465618377; +inv_value(112) -> 40917382598701773375164871210344989403; +inv_value(113) -> 32733906078961418700131896968275991523; +inv_value(114) -> 26187124863169134960105517574620793218; +inv_value(115) -> 41899399781070615936168828119393269149; +inv_value(116) -> 33519519824856492748935062495514615319; +inv_value(117) -> 26815615859885194199148049996411692255; +inv_value(118) -> 21452492687908155359318439997129353804; +inv_value(119) -> 34323988300653048574909503995406966087; +inv_value(120) -> 27459190640522438859927603196325572870; +inv_value(121) -> 21967352512417951087942082557060458296; +inv_value(122) -> 35147764019868721740707332091296733273; +inv_value(123) -> 28118211215894977392565865673037386618; +inv_value(124) -> 22494568972715981914052692538429909295; +inv_value(125) -> 35991310356345571062484308061487854871; +inv_value(126) -> 28793048285076456849987446449190283897; +inv_value(127) -> 23034438628061165479989957159352227118; +inv_value(128) -> 36855101804897864767983931454963563388; +inv_value(129) -> 29484081443918291814387145163970850711; +inv_value(130) -> 23587265155134633451509716131176680569; +inv_value(131) -> 37739624248215413522415545809882688910; +inv_value(132) -> 30191699398572330817932436647906151128; +inv_value(133) -> 24153359518857864654345949318324920902; +inv_value(134) -> 38645375230172583446953518909319873443; +inv_value(135) -> 30916300184138066757562815127455898755; +inv_value(136) -> 24733040147310453406050252101964719004; +inv_value(137) -> 39572864235696725449680403363143550406; +inv_value(138) -> 31658291388557380359744322690514840325; +inv_value(139) -> 25326633110845904287795458152411872260; +inv_value(140) -> 40522612977353446860472733043858995616; +inv_value(141) -> 32418090381882757488378186435087196493; +inv_value(142) -> 25934472305506205990702549148069757194; +inv_value(143) -> 41495155688809929585124078636911611511; +inv_value(144) -> 33196124551047943668099262909529289209; +inv_value(145) -> 26556899640838354934479410327623431367; +inv_value(146) -> 42491039425341367895167056524197490187; +inv_value(147) -> 33992831540273094316133645219357992150; +inv_value(148) -> 27194265232218475452906916175486393720; +inv_value(149) -> 21755412185774780362325532940389114976; +inv_value(150) -> 34808659497239648579720852704622583961; +inv_value(151) -> 27846927597791718863776682163698067169; +inv_value(152) -> 22277542078233375091021345730958453735; +inv_value(153) -> 35644067325173400145634153169533525976; +inv_value(154) -> 28515253860138720116507322535626820781; +inv_value(155) -> 22812203088110976093205858028501456625; +inv_value(156) -> 36499524940977561749129372845602330600; +inv_value(157) -> 29199619952782049399303498276481864480; +inv_value(158) -> 23359695962225639519442798621185491584; +inv_value(159) -> 37375513539561023231108477793896786534; +inv_value(160) -> 29900410831648818584886782235117429227; +inv_value(161) -> 23920328665319054867909425788093943382; +inv_value(162) -> 38272525864510487788655081260950309411; +inv_value(163) -> 30618020691608390230924065008760247529; +inv_value(164) -> 24494416553286712184739252007008198023; +inv_value(165) -> 39191066485258739495582803211213116837; +inv_value(166) -> 31352853188206991596466242568970493469; +inv_value(167) -> 25082282550565593277172994055176394776; +inv_value(168) -> 40131652080904949243476790488282231641; +inv_value(169) -> 32105321664723959394781432390625785313; +inv_value(170) -> 25684257331779167515825145912500628250; +inv_value(171) -> 41094811730846668025320233460001005200; +inv_value(172) -> 32875849384677334420256186768000804160; +inv_value(173) -> 26300679507741867536204949414400643328; +inv_value(174) -> 42081087212386988057927919063041029325; +inv_value(175) -> 33664869769909590446342335250432823460; +inv_value(176) -> 26931895815927672357073868200346258768; +inv_value(177) -> 21545516652742137885659094560277007015; +inv_value(178) -> 34472826644387420617054551296443211223; +inv_value(179) -> 27578261315509936493643641037154568979; +inv_value(180) -> 22062609052407949194914912829723655183; +inv_value(181) -> 35300174483852718711863860527557848292; +inv_value(182) -> 28240139587082174969491088422046278634; +inv_value(183) -> 22592111669665739975592870737637022907; +inv_value(184) -> 36147378671465183960948593180219236651; +inv_value(185) -> 28917902937172147168758874544175389321; +inv_value(186) -> 23134322349737717735007099635340311457; +inv_value(187) -> 37014915759580348376011359416544498331; +inv_value(188) -> 29611932607664278700809087533235598665; +inv_value(189) -> 23689546086131422960647270026588478932; +inv_value(190) -> 37903273737810276737035632042541566291; +inv_value(191) -> 30322618990248221389628505634033253033; +inv_value(192) -> 24258095192198577111702804507226602426; +inv_value(193) -> 38812952307517723378724487211562563882; +inv_value(194) -> 31050361846014178702979589769250051106; +inv_value(195) -> 24840289476811342962383671815400040885; +inv_value(196) -> 39744463162898148739813874904640065415; +inv_value(197) -> 31795570530318518991851099923712052332; +inv_value(198) -> 25436456424254815193480879938969641866; +inv_value(199) -> 40698330278807704309569407902351426985; +inv_value(200) -> 32558664223046163447655526321881141588; +inv_value(201) -> 26046931378436930758124421057504913271; +inv_value(202) -> 41675090205499089212999073692007861233; +inv_value(203) -> 33340072164399271370399258953606288986; +inv_value(204) -> 26672057731519417096319407162885031189; +inv_value(205) -> 21337646185215533677055525730308024951; +inv_value(206) -> 34140233896344853883288841168492839922; +inv_value(207) -> 27312187117075883106631072934794271938; +inv_value(208) -> 21849749693660706485304858347835417550; +inv_value(209) -> 34959599509857130376487773356536668080; +inv_value(210) -> 27967679607885704301190218685229334464; +inv_value(211) -> 22374143686308563440952174948183467571; +inv_value(212) -> 35798629898093701505523479917093548114; +inv_value(213) -> 28638903918474961204418783933674838491; +inv_value(214) -> 22911123134779968963535027146939870793; +inv_value(215) -> 36657797015647950341656043435103793269; +inv_value(216) -> 29326237612518360273324834748083034615; +inv_value(217) -> 23460990090014688218659867798466427692; +inv_value(218) -> 37537584144023501149855788477546284307; +inv_value(219) -> 30030067315218800919884630782037027446; +inv_value(220) -> 24024053852175040735907704625629621957; +inv_value(221) -> 38438486163480065177452327401007395130; +inv_value(222) -> 30750788930784052141961861920805916104; +inv_value(223) -> 24600631144627241713569489536644732884; +inv_value(224) -> 39361009831403586741711183258631572614; +inv_value(225) -> 31488807865122869393368946606905258091; +inv_value(226) -> 25191046292098295514695157285524206473; +inv_value(227) -> 40305674067357272823512251656838730356; +inv_value(228) -> 32244539253885818258809801325470984285; +inv_value(229) -> 25795631403108654607047841060376787428; +inv_value(230) -> 41273010244973847371276545696602859885; +inv_value(231) -> 33018408195979077897021236557282287908; +inv_value(232) -> 26414726556783262317616989245825830326; +inv_value(233) -> 42263562490853219708187182793321328522; +inv_value(234) -> 33810849992682575766549746234657062818; +inv_value(235) -> 27048679994146060613239796987725650254; +inv_value(236) -> 21638943995316848490591837590180520204; +inv_value(237) -> 34622310392506957584946940144288832325; +inv_value(238) -> 27697848314005566067957552115431065860; +inv_value(239) -> 22158278651204452854366041692344852688; +inv_value(240) -> 35453245841927124566985666707751764301; +inv_value(241) -> 28362596673541699653588533366201411441; +inv_value(242) -> 22690077338833359722870826692961129153; +inv_value(243) -> 36304123742133375556593322708737806644; +inv_value(244) -> 29043298993706700445274658166990245316; +inv_value(245) -> 23234639194965360356219726533592196253; +inv_value(246) -> 37175422711944576569951562453747514004; +inv_value(247) -> 29740338169555661255961249962998011203; +inv_value(248) -> 23792270535644529004768999970398408963; +inv_value(249) -> 38067632857031246407630399952637454340; +inv_value(250) -> 30454106285624997126104319962109963472; +inv_value(251) -> 24363285028499997700883455969687970778; +inv_value(252) -> 38981256045599996321413529551500753244; +inv_value(253) -> 31185004836479997057130823641200602595; +inv_value(254) -> 24948003869183997645704658912960482076; +inv_value(255) -> 39916806190694396233127454260736771322; +inv_value(256) -> 31933444952555516986501963408589417058; +inv_value(257) -> 25546755962044413589201570726871533646; +inv_value(258) -> 40874809539271061742722513162994453834; +inv_value(259) -> 32699847631416849394178010530395563067; +inv_value(260) -> 26159878105133479515342408424316450454; +inv_value(261) -> 41855804968213567224547853478906320726; +inv_value(262) -> 33484643974570853779638282783125056581; +inv_value(263) -> 26787715179656683023710626226500045265; +inv_value(264) -> 21430172143725346418968500981200036212; +inv_value(265) -> 34288275429960554270349601569920057938; +inv_value(266) -> 27430620343968443416279681255936046351; +inv_value(267) -> 21944496275174754733023745004748837081; +inv_value(268) -> 35111194040279607572837992007598139329; +inv_value(269) -> 28088955232223686058270393606078511463; +inv_value(270) -> 22471164185778948846616314884862809171; +inv_value(271) -> 35953862697246318154586103815780494673; +inv_value(272) -> 28763090157797054523668883052624395738; +inv_value(273) -> 23010472126237643618935106442099516591; +inv_value(274) -> 36816755401980229790296170307359226545; +inv_value(275) -> 29453404321584183832236936245887381236; +inv_value(276) -> 23562723457267347065789548996709904989; +inv_value(277) -> 37700357531627755305263278394735847982; +inv_value(278) -> 30160286025302204244210622715788678386; +inv_value(279) -> 24128228820241763395368498172630942709; +inv_value(280) -> 38605166112386821432589597076209508334; +inv_value(281) -> 30884132889909457146071677660967606667; +inv_value(282) -> 24707306311927565716857342128774085334; +inv_value(283) -> 39531690099084105146971747406038536534; +inv_value(284) -> 31625352079267284117577397924830829227; +inv_value(285) -> 25300281663413827294061918339864663382; +inv_value(286) -> 40480450661462123670499069343783461410; +inv_value(287) -> 32384360529169698936399255475026769128; +inv_value(288) -> 25907488423335759149119404380021415303; +inv_value(289) -> 41451981477337214638591047008034264484; +inv_value(290) -> 33161585181869771710872837606427411587; +inv_value(291) -> 26529268145495817368698270085141929270; +inv_value(292) -> 42446829032793307789917232136227086832; +inv_value(293) -> 33957463226234646231933785708981669466; +inv_value(294) -> 27165970580987716985547028567185335573; +inv_value(295) -> 21732776464790173588437622853748268458; +inv_value(296) -> 34772442343664277741500196565997229533; +inv_value(297) -> 27817953874931422193200157252797783626; +inv_value(298) -> 22254363099945137754560125802238226901; +inv_value(299) -> 35606980959912220407296201283581163042; +inv_value(300) -> 28485584767929776325836961026864930433; +inv_value(301) -> 22788467814343821060669568821491944347; +inv_value(302) -> 36461548502950113697071310114387110955; +inv_value(303) -> 29169238802360090957657048091509688764; +inv_value(304) -> 23335391041888072766125638473207751011; +inv_value(305) -> 37336625667020916425801021557132401617; +inv_value(306) -> 29869300533616733140640817245705921294; +inv_value(307) -> 23895440426893386512512653796564737035; +inv_value(308) -> 38232704683029418420020246074503579256; +inv_value(309) -> 30586163746423534736016196859602863405; +inv_value(310) -> 24468930997138827788812957487682290724; +inv_value(311) -> 39150289595422124462100731980291665158; +inv_value(312) -> 31320231676337699569680585584233332127; +inv_value(313) -> 25056185341070159655744468467386665702; +inv_value(314) -> 40089896545712255449191149547818665122; +inv_value(315) -> 32071917236569804359352919638254932098; +inv_value(316) -> 25657533789255843487482335710603945678; +inv_value(317) -> 41052054062809349579971737136966313085; +inv_value(318) -> 32841643250247479663977389709573050468; +inv_value(319) -> 26273314600197983731181911767658440375; +inv_value(320) -> 42037303360316773969891058828253504599; +inv_value(321) -> 33629842688253419175912847062602803679; +inv_value(322) -> 26903874150602735340730277650082242944; +inv_value(323) -> 21523099320482188272584222120065794355; +inv_value(324) -> 34436958912771501236134755392105270968; +inv_value(325) -> 27549567130217200988907804313684216774; +inv_value(326) -> 22039653704173760791126243450947373419; +inv_value(327) -> 35263445926678017265801989521515797471; +inv_value(328) -> 28210756741342413812641591617212637977; +inv_value(329) -> 22568605393073931050113273293770110382; +inv_value(330) -> 36109768628918289680181237270032176610; +inv_value(331) -> 28887814903134631744144989816025741288; +inv_value(332) -> 23110251922507705395315991852820593031; +inv_value(333) -> 36976403076012328632505586964512948849; +inv_value(334) -> 29581122460809862906004469571610359079; +inv_value(335) -> 23664897968647890324803575657288287263; +inv_value(336) -> 37863836749836624519685721051661259621; +inv_value(337) -> 30291069399869299615748576841329007697; +inv_value(338) -> 24232855519895439692598861473063206158; +inv_value(339) -> 38772568831832703508158178356901129852; +inv_value(340) -> 31018055065466162806526542685520903882; +inv_value(341) -> 24814444052372930245221234148416723105; +inv_value(_) -> error(function_clause). diff --git a/lib/stdlib/src/stdlib.app.src b/lib/stdlib/src/stdlib.app.src index 9c580bffca..a906349463 100644 --- a/lib/stdlib/src/stdlib.app.src +++ b/lib/stdlib/src/stdlib.app.src @@ -71,6 +71,7 @@ io, io_lib, io_lib_format, + io_lib_format_ryu_table, io_lib_fread, io_lib_pretty, lists, diff --git a/lib/stdlib/test/io_SUITE.erl b/lib/stdlib/test/io_SUITE.erl index bb59a5e53f..22b598c3c0 100644 --- a/lib/stdlib/test/io_SUITE.erl +++ b/lib/stdlib/test/io_SUITE.erl @@ -985,15 +985,12 @@ otp_7084(Config) when is_list(Config) -> {g_denormalized, fun g_denormalized/0}, {g_normalized, fun g_normalized/0}, {g_choice, fun g_choice/0}, + {g_ryu, fun g_ryu/0}, + {g_anomalous, fun g_anomalous/0}, {g_misc, fun g_misc/0}], F = fun({M,T}) -> io:format("~p~n", [M]), T() end, - R = try - lists:foreach(fun(T) -> F(T) end, L), - ok - catch throw:Reason -> - Reason - end, - R. + lists:foreach(fun(T) -> F(T) end, L), + ok. g_warm_up() -> g_t(0.5), @@ -1041,13 +1038,188 @@ g_normalized() -> g_choice() -> %% Exponent should be used when and only when the string is shorter. %% (g_misc/0 checks this too, and probably more throughly). - L = [0.0003, 3.0e-5, 3.3e-5, 3.3e-4, - 314.0, 314.1, 310.0, 3.1e6, -100.0, - 3.34e4, 3.0e3, 3.34333e9, 3.3433323e10, 33433323700.0, + L = [0.0003, 3.0e-5, 3.3e-5, 3.3e-4, + 314.0, 314.1, 310.0, 3.1e6, -100.0, + 3.34e4, 3.0e3, 3.34333e9, 3.3433323e10, 33433323700.0, 0.00197963, 1.97963e-4], lists:foreach(fun(V) -> g_t(V) end, L), ok. +g_anomalous() -> + %% These test cases come from https://github.com/microsoft/STL/blob/f1515e04fd00876137e762c08b90d9aa450859e0/tests/std/tests/P0067R5_charconv/double_to_chars_test_cases.hpp + + %% https://www.exploringbinary.com/the-shortest-decimal-string-that-round-trips-may-not-be-the-nearest/ + %% This is an exhaustive list of anomalous values + %% Because math, these values have shortest-round-trip decimal representations containing 16 significant digits, + %% but those decimal digits aren't what would be printed by "%.15e". For ordinary values, shortest-round-trip + %% behaves as if it can magically pick a precision for "%.*e", finding the smallest precision that round-trips. + %% (That is, start with the exact decimal representation, and then round it as much as possible.) These anomalous + %% values demonstrate an exception to that mental model. They aren't being "incorrectly rounded"; instead, having + %% the shortest output that round-trips is being prioritized. (This differs by 1 in the least significant decimal + %% digit printed, so it's a very small difference.) + + L_anom = [6.386688990511104e+293, 5.282945311356653e+269, + 6.150157786156811e+259, 5.334411546303884e+241, + 5.386379163185535e+213, 6.483618076376552e+178, + 6.183260036827614e+172, 5.896816288783659e+166, + 5.758609657015292e+163, 5.623642243178996e+160, + 6.243497100631985e+144, 8.263199609878108e+121, + 6.455624695217272e+119, 6.156563468186638e+113, + 7.167183174968974e+103, 6.518515124270356e+91, + 6.070840288205404e+82, 6.129982163463556e+54, + 5.986310706507379e+51, 5.444517870735016e+39, + 5.316911983139664e+36, 6.189700196426902e+26, + 5.960464477539063e-08, 5.684341886080802e-14, + 6.617444900424222e-24, 6.310887241768095e-30, + 7.174648137343064e-43, 7.854549544476363e-90, + 6.653062250012736e-111, 5.075883674631299e-116, + 6.256509672447191e-148, 4.887898181599368e-150, + 5.966672584960166e-154, 5.426657103235053e-166, + 5.351097043477547e-197, 5.225680706521042e-200, + 6.083493012144512e-210, 5.940911144672375e-213, + 6.290184345309701e-235, 6.142758149716505e-238, + 7.678447687145631e-239, 5.858190679279809e-244, + 5.641232424577593e-278, 8.209073602596753e-289, + 7.291122019556398e-304, 7.120236347223045e-307], + lists:foreach(fun(V) -> g_t(V) end, L_anom), + + %% This is an exhaustive list of almost-but-not-quite-anomalous values. + L_quasi_anom = [6.237000967296e+290, 6.090821257125e+287, + 8.25460204899477e+267, 5.78358058743443e+222, + 7.1362384635298e+44, 6.10987272699921e-151, + 5.17526350329881e-172, 6.84940421565126e-195], + lists:foreach(fun(V) -> g_t(V) end, L_quasi_anom), + + ok. + +g_ryu() -> + %% specific white box tests that should trigger specific edge cases + %% to the ryu algorithm see: + %% https://github.com/ulfjack/ryu/blob/master/ryu/tests/d2s_test.cc + + %% this list is regression tests from the ryu C ref implementation + L_regression = [-2.109808898695963e16, 4.940656e-318, 1.18575755E-316, + 2.989102097996e-312, 9.0608011534336e15, + 4.708356024711512e18, 9.409340012568248e18, + 1.2345678], + lists:foreach(fun(V) -> g_t(V) end, L_regression), + + %% These numbers have a mantissa that is a multiple of the largest power of 5 that fits, + %% and an exponent that causes the computation for q to result in 22, which is a corner + %% case for Ryu. + L_pow5 = [16#4830F0CF064DD592, 16#4840F0CF064DD592, + 16#4850F0CF064DD592], + lists:foreach(fun(V) -> g_t(i_2_d(V)) end, L_pow5), + + %% Test 32-bit chunking 2^32 +- 1/2 + L_32bits = [4.294967294, 4.294967295, 4.294967296, 4.294967297, + 4.294967298], + lists:foreach(fun(V) -> g_t(V) end, L_32bits), + + %% Test 32-bit chunking 2^32 +- 1/2 + L_32bits = [4.294967294, 4.294967295, 4.294967296, 4.294967297, + 4.294967298], + lists:foreach(fun(V) -> g_t(V) end, L_32bits), + + L = [1.2e+1, 1.23e+2, 1.234e+3, 1.2345e+4, 1.23456e+5, 1.234567e+6, + 1.2345678e+7, 1.23456789e+8, 1.23456789e+9, 1.234567895e+9, + 1.2345678901e+10, 1.23456789012e+11, 1.234567890123e+12, + 1.2345678901234e+13, 1.23456789012345e+14, 1.234567890123456e+15], + lists:foreach(fun(V) -> g_t(V) end, L), + + %% power of 2 + L_pow2 = [8.0, 64.0, 512.0, 8192.0, 65536.0, 524288.0, 8388608.0, + 67108864.0, 536870912.0, 8589934592.0, 68719476736.0, + 549755813888.0, 8796093022208.0, 70368744177664.0, + 562949953421312.0, 9007199254740992.0], + lists:foreach(fun(V) -> g_t(V) end, L_pow2), + + %% 1000 * power of 2 + L_pow2_1000 = [8.0e+3, 64.0e+3, 512.0e+3, 8192.0e+3, 65536.0e+3, + 524288.0e+3, 8388608.0e+3, 67108864.0e+3, 536870912.0e+3, + 8589934592.0e+3, 68719476736.0e+3, 549755813888.0e+3, + 8796093022208.0e+3], + lists:foreach(fun(V) -> g_t(V) end, L_pow2_1000), + + %% 10^15 + 10^i + L_pow10_plus = [1.0e+15 + 1.0e+0, 1.0e+15 + 1.0e+1, 1.0e+15 + 1.0e+2, + 1.0e+15 + 1.0e+3, 1.0e+15 + 1.0e+4, 1.0e+15 + 1.0e+5, + 1.0e+15 + 1.0e+6, 1.0e+15 + 1.0e+7, 1.0e+15 + 1.0e+8, + 1.0e+15 + 1.0e+9, 1.0e+15 + 1.0e+10, 1.0e+15 + 1.0e+11, + 1.0e+15 + 1.0e+12, 1.0e+15 + 1.0e+13, 1.0e+15 + 1.0e+14], + lists:foreach(fun(V) -> g_t(V) end, L_pow10_plus), + + %% min and max + g_t(i_2_d(1)), + g_t(i_2_d(16#7fefffffffffffff)), + + %% lots of trailing zeroes + g_t(2.98023223876953125e-8), + + %% Switch to Subnormal + g_t(2.2250738585072014e-308), + + %% special case to check for the shift to the right by 128 + L_shift = [parts_2_f(0, 4,0), parts_2_f(0, 6, (1 bsl 53) - 1), + parts_2_f(0, 41, 0), parts_2_f(0, 40, (1 bsl 53) - 1), + parts_2_f(0, 1077, 0), parts_2_f(0, 1076, (1 bsl 53) - 1), + parts_2_f(0, 307, 0), parts_2_f(0, 306, (1 bsl 53) - 1), + parts_2_f(0, 934, 16#000FA7161A4D6E0C)], + lists:foreach(fun(V) -> g_t(V) end, L_shift), + + %% following test cases come from https://github.com/microsoft/STL/blob/f1515e04fd00876137e762c08b90d9aa450859e0/tests/std/tests/P0067R5_charconv/double_to_chars_test_cases.hpp + %% These numbers have odd mantissas (unaffected by shifting) + %% that are barely within the "max shifted mantissa" limit. + + L_mantissas_within_limit = [ + 1801439850948197.0e1, 360287970189639.0e2, 72057594037927.0e3, + 14411518807585.0e4, 2882303761517.0e5, 576460752303.0e6, + 115292150459.0e7, 23058430091.0e8, 4611686017.0e9, 922337203.0e10, + 184467439.0e11, 36893487.0e12, 7378697.0e13, 1475739.0e14, + 295147.0e15, 59029.0e16, 11805.0e17, 2361.0e18, 471.0e19, 93.0e20, + 17.0e21, 3.0e22], + lists:foreach(fun(V) -> g_t(V) end, L_mantissas_within_limit), + + %% These numbers have odd mantissas (unaffected by shifting) + %% that are barely above the "max shifted mantissa" limit. + L_mantissas_above_limit = [ + 1801439850948199.0e1, 360287970189641.0e2, 72057594037929.0e3, + 14411518807587.0e4, 2882303761519.0e5, 576460752305.0e6, + 115292150461.0e7, 23058430093.0e8, 4611686019.0e9, 922337205.0e10, + 184467441.0e11, 36893489.0e12, 7378699.0e13, 1475741.0e14, + 295149.0e15, 59031.0e16, 11807.0e17, 2363.0e18, 473.0e19, 95.0e20, + 19.0e21, 5.0e22], + lists:foreach(fun(V) -> g_t(V) end, L_mantissas_above_limit), + + L_switch = [1801439850948197.0e1, 360287970189639.0e2, 72057594037927.0e3, + 14411518807585.0e4, 2882303761517.0e5, 576460752303.0e6, + 115292150459.0e7, 23058430091.0e8, 4611686017.0e9, + 922337203.0e10, 184467439.0e11, 36893487.0e12, 7378697.0e13, + 1475739.0e14, 295147.0e15, 59029.0e16, 11805.0e17, 2361.0e18, + 471.0e19, 93.0e20, 17.0e21, 3.0e22, 1801439850948199.0e1, + 360287970189641.0e2, 72057594037929.0e3, 14411518807587.0e4, + 2882303761519.0e5, 576460752305.0e6, 115292150461.0e7, + 23058430093.0e8, 4611686019.0e9, 922337205.0e10, + 184467441.0e11, 36893489.0e12, 7378699.0e13, 1475741.0e14, + 295149.0e15, 59031.0e16, 11807.0e17, 2363.0e18, 473.0e19, + 95.0e20, 19.0e21, 5.0e22, 302230528.0e15, 302232576.0e15, + 81123342286848.0e18, 81192061763584.0e18], + lists:foreach(fun(V) -> g_t(V) end, L_switch), + + L_edge = [123456789012345683968.0, 1.9156918820264798e-56, + 6.6564021122018745e+264, 4.91e-6, 5.547e-6], + lists:foreach(fun(V) -> g_t(V) end, L_edge), + + ok. + +i_2_d(Int) -> + <<F:64/float>> = <<Int:64/unsigned-integer>>, + F. + +parts_2_f(S, E, M) -> + <<F:64/float>> = <<S:1, E:11, M:52>>, + F. + g_misc() -> L_0_308 = lists:seq(0, 308), L_0_307 = lists:seq(0, 307), -- 2.26.2
Locations
Projects
Search
Status Monitor
Help
OpenBuildService.org
Documentation
API Documentation
Code of Conduct
Contact
Support
@OBShq
Terms
openSUSE Build Service is sponsored by
The Open Build Service is an
openSUSE project
.
Sign Up
Log In
Places
Places
All Projects
Status Monitor