aboutsummaryrefslogtreecommitdiffstats
path: root/erts/emulator/test/num_bif_SUITE.erl
diff options
context:
space:
mode:
Diffstat (limited to 'erts/emulator/test/num_bif_SUITE.erl')
-rw-r--r--erts/emulator/test/num_bif_SUITE.erl147
1 files changed, 126 insertions, 21 deletions
diff --git a/erts/emulator/test/num_bif_SUITE.erl b/erts/emulator/test/num_bif_SUITE.erl
index f31e73c85b..d950179882 100644
--- a/erts/emulator/test/num_bif_SUITE.erl
+++ b/erts/emulator/test/num_bif_SUITE.erl
@@ -32,6 +32,8 @@
%% list_to_integer/1
%% round/1
%% trunc/1
+%% floor/1
+%% ceil/1
%% integer_to_binary/1
%% integer_to_binary/2
%% binary_to_integer/1
@@ -41,7 +43,7 @@
t_float_to_string/1, t_integer_to_string/1,
t_string_to_integer/1, t_list_to_integer_edge_cases/1,
t_string_to_float_safe/1, t_string_to_float_risky/1,
- t_round/1, t_trunc/1
+ t_round/1, t_trunc_and_friends/1
]).
suite() -> [{ct_hooks,[ts_install_cth]}].
@@ -49,7 +51,7 @@ suite() -> [{ct_hooks,[ts_install_cth]}].
all() ->
[t_abs, t_float, t_float_to_string, t_integer_to_string,
{group, t_string_to_float}, t_string_to_integer, t_round,
- t_trunc, t_list_to_integer_edge_cases].
+ t_trunc_and_friends, t_list_to_integer_edge_cases].
groups() ->
[{t_string_to_float, [],
@@ -106,7 +108,7 @@ t_float(Config) when is_list(Config) ->
4294967305.0 = float(id(4294967305)),
-4294967305.0 = float(id(-4294967305)),
- %% Extremly big bignums.
+ %% Extremely big bignums.
Big = id(list_to_integer(id(lists:duplicate(2000, $1)))),
{'EXIT', {badarg, _}} = (catch float(Big)),
@@ -116,6 +118,7 @@ t_float(Config) when is_list(Config) ->
%% Tests float_to_list/1, float_to_list/2, float_to_binary/1, float_to_binary/2
t_float_to_string(Config) when is_list(Config) ->
+ rand_seed(),
test_fts("0.00000000000000000000e+00", 0.0),
test_fts("2.50000000000000000000e+01", 25.0),
test_fts("2.50000000000000000000e+00", 2.5),
@@ -165,8 +168,8 @@ t_float_to_string(Config) when is_list(Config) ->
test_fts("1.12300",1.123, [{decimals, 5}]),
test_fts("1.123",1.123, [{decimals, 5}, compact]),
test_fts("1.1234",1.1234,[{decimals, 6}, compact]),
- test_fts("1.01",1.005, [{decimals, 2}]),
- test_fts("-1.01",-1.005,[{decimals, 2}]),
+ test_fts("1.00",1.005, [{decimals, 2}]), %% 1.005 is really 1.0049999999...
+ test_fts("-1.00",-1.005,[{decimals, 2}]),
test_fts("0.999",0.999, [{decimals, 3}]),
test_fts("-0.999",-0.999,[{decimals, 3}]),
test_fts("1.0",0.999, [{decimals, 2}, compact]),
@@ -182,6 +185,9 @@ t_float_to_string(Config) when is_list(Config) ->
test_fts("123000000000000000000.0",1.23e20, [{decimals, 10}, compact]),
test_fts("1.2300000000e+20",1.23e20, [{scientific, 10}, compact]),
test_fts("1.23000000000000000000e+20",1.23e20, []),
+
+ fts_rand_float_decimals(1000),
+
ok.
test_fts(Expect, Float) ->
@@ -195,6 +201,49 @@ test_fts(Expect, Float, Args) ->
BinExpect = float_to_binary(Float,Args).
+rand_float_reasonable() ->
+ F = rand_float(),
+ case abs(F) > 1.0e238 of
+ true -> rand_float_reasonable();
+ false -> F
+ end.
+
+fts_rand_float_decimals(0) -> ok;
+fts_rand_float_decimals(N) ->
+ [begin
+ F0 = rand_float_reasonable(),
+ L0 = float_to_list(F0, [{decimals, D}]),
+ L1 = case D of
+ 0 -> L0 ++ ".0";
+ _ -> L0
+ end,
+ F1 = list_to_float(L1),
+ Diff = abs(F0-F1),
+ MaxDiff = max_diff_decimals(F0, D),
+ ok = case Diff =< MaxDiff of
+ true -> ok;
+ false ->
+ io:format("F0 = ~w ~w\n", [F0, <<F0/float>>]),
+ io:format("L1 = ~s\n", [L1]),
+ io:format("F1 = ~w ~w\n", [F1, <<F1/float>>]),
+ io:format("Diff = ~w, MaxDiff = ~w\n", [Diff, MaxDiff]),
+ error
+ end
+ end
+ || D <- lists:seq(0,15)],
+
+ fts_rand_float_decimals(N-1).
+
+max_diff_decimals(F, D) ->
+ IntBits = floor(math:log2(abs(F))) + 1,
+ FracBits = (52 - IntBits),
+ Log10_2 = 0.3010299956639812, % math:log10(2)
+ MaxDec = floor(FracBits * Log10_2),
+
+ Resolution = math:pow(2, IntBits - 53),
+
+ (math:pow(10, -min(D,MaxDec)) / 2) + Resolution.
+
%% Tests list_to_float/1.
t_string_to_float_safe(Config) when is_list(Config) ->
@@ -298,30 +347,86 @@ t_round(Config) when is_list(Config) ->
-6209607916799025 = round(id(-6209607916799025.0)),
ok.
-t_trunc(Config) when is_list(Config) ->
- 0 = trunc(id(0.0)),
- 5 = trunc(id(5.3333)),
- -10 = trunc(id(-10.978987)),
+%% Test trunc/1, floor/1, ceil/1, and round/1.
+t_trunc_and_friends(_Config) ->
+ MinusZero = 0.0 / (-1.0),
+ 0 = trunc_and_friends(MinusZero),
+ 0 = trunc_and_friends(0.0),
+ 5 = trunc_and_friends(5.3333),
+ -10 = trunc_and_friends(-10.978987),
- % The largest smallnum, converted to float (OTP-3722):
+ %% The largest smallnum, converted to float (OTP-3722):
X = id((1 bsl 27) - 1),
- F = id(X + 0.0),
+ F = X + 0.0,
io:format("X = ~p/~w/~w, F = ~p/~w/~w, trunc(F) = ~p/~w/~w~n",
[X, X, binary_to_list(term_to_binary(X)),
F, F, binary_to_list(term_to_binary(F)),
- trunc(F), trunc(F), binary_to_list(term_to_binary(trunc(F)))]),
- X = trunc(F),
- X = trunc(F+1)-1,
- X = trunc(F-1)+1,
- X = -trunc(-F),
- X = -trunc(-F-1)-1,
- X = -trunc(-F+1)+1,
+ trunc_and_friends(F),
+ trunc_and_friends(F),
+ binary_to_list(term_to_binary(trunc_and_friends(F)))]),
+ X = trunc_and_friends(F),
+ X = trunc_and_friends(F+1)-1,
+ X = trunc_and_friends(F-1)+1,
+ X = -trunc_and_friends(-F),
+ X = -trunc_and_friends(-F-1)-1,
+ X = -trunc_and_friends(-F+1)+1,
%% Bignums.
- 4294967305 = trunc(id(4294967305.7)),
- -4294967305 = trunc(id(-4294967305.7)),
+ 4294967305 = trunc_and_friends(4294967305.7),
+ -4294967305 = trunc_and_friends(-4294967305.7),
+ 18446744073709551616 = trunc_and_friends(float(1 bsl 64)),
+ -18446744073709551616 = trunc_and_friends(-float(1 bsl 64)),
+
+ %% Random.
+ rand_seed(),
+ t_trunc_and_friends_rand(100),
+ ok.
+
+rand_seed() ->
+ rand:seed(exrop),
+ io:format("\n*** rand:export_seed() = ~w\n\n", [rand:export_seed()]),
ok.
+rand_float() ->
+ F0 = rand:uniform() * math:pow(10, 50*rand:normal()),
+ case rand:uniform() of
+ U when U < 0.5 -> -F0;
+ _ -> F0
+ end.
+
+t_trunc_and_friends_rand(0) ->
+ ok;
+t_trunc_and_friends_rand(N) ->
+ _ = trunc_and_friends(rand_float()),
+ t_trunc_and_friends_rand(N-1).
+
+trunc_and_friends(F) ->
+ Trunc = trunc(F),
+ Floor = floor(F),
+ Ceil = ceil(F),
+ Round = round(F),
+
+ Trunc = trunc(Trunc),
+ Floor = floor(Floor),
+ Ceil = ceil(Ceil),
+ Round = round(Round),
+
+ Trunc = trunc(float(Trunc)),
+ Floor = floor(float(Floor)),
+ Ceil = ceil(float(Ceil)),
+ Round = round(float(Round)),
+
+ true = Floor =< Trunc andalso Trunc =< Ceil,
+ true = Ceil - Floor =< 1,
+ true = Round =:= Floor orelse Round =:= Ceil,
+
+ if
+ F < 0 ->
+ Trunc = Ceil;
+ true ->
+ Trunc = Floor
+ end,
+ Trunc.
%% Tests integer_to_binary/1.
@@ -441,7 +546,7 @@ t_string_to_integer(Config) when is_list(Config) ->
list_to_binary(Value),Base)),
{'EXIT', {badarg, _}} =
(catch erlang:list_to_integer(Value,Base))
- end,[{" 1",1},{" 1",37},{"2",2},{"C",11},
+ end,[{" 1",1},{" 1",37},{"2",2},{"B",11},{"b",11},{":", 16},
{"1111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111z",16},
{"1z111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111",16},
{"111z11111111",16}]),