aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBjörn Gustavsson <[email protected]>2016-09-05 11:50:33 +0200
committerBjörn Gustavsson <[email protected]>2016-09-05 11:50:33 +0200
commit6150c222ec25cc4e8aba80985017c5b7120bc454 (patch)
tree9c149f8d7b3d6c8135fcfe0b73b3dae8d88800d7
parentb501396623e80a798fba94a428646461aabe6796 (diff)
parent6d40cfd77f1d2f1e1403e4b41c0b53ae6499ea11 (diff)
downloadotp-6150c222ec25cc4e8aba80985017c5b7120bc454.tar.gz
otp-6150c222ec25cc4e8aba80985017c5b7120bc454.tar.bz2
otp-6150c222ec25cc4e8aba80985017c5b7120bc454.zip
Merge branch 'bjorn/floor-ceiling/OTP-13692'
* bjorn/floor-ceiling/OTP-13692: Add math:floor/1 and math:ceil/1 Implement the new ceil/1 and floor/1 guard BIFs
-rw-r--r--erts/doc/src/erlang.xml27
-rw-r--r--erts/emulator/beam/bif.tab9
-rw-r--r--erts/emulator/beam/erl_bif_guard.c65
-rw-r--r--erts/emulator/beam/erl_math.c10
-rw-r--r--erts/emulator/test/num_bif_SUITE.erl84
-rw-r--r--erts/preloaded/ebin/erlang.beambin105100 -> 105400 bytes
-rw-r--r--erts/preloaded/src/erlang.erl19
-rw-r--r--lib/compiler/src/beam_type.erl2
-rw-r--r--lib/compiler/src/beam_validator.erl4
-rw-r--r--lib/compiler/src/erl_bifs.erl4
-rw-r--r--lib/compiler/src/sys_core_fold.erl2
-rw-r--r--lib/compiler/test/bif_SUITE.erl4
-rw-r--r--lib/compiler/test/float_SUITE.erl5
-rw-r--r--lib/hipe/cerl/erl_bif_types.erl12
-rw-r--r--lib/stdlib/doc/src/math.xml2
-rw-r--r--lib/stdlib/src/erl_internal.erl4
-rw-r--r--lib/stdlib/src/math.erl13
-rw-r--r--lib/stdlib/test/Makefile1
-rw-r--r--lib/stdlib/test/math_SUITE.erl92
-rw-r--r--lib/tools/emacs/erlang.el2
20 files changed, 337 insertions, 24 deletions
diff --git a/erts/doc/src/erlang.xml b/erts/doc/src/erlang.xml
index d0a3a77e43..18a7a5b777 100644
--- a/erts/doc/src/erlang.xml
+++ b/erts/doc/src/erlang.xml
@@ -718,6 +718,19 @@ Z = erlang:adler32_combine(X,Y,iolist_size(Data2)).</code>
</func>
<func>
+ <name name="ceil" arity="1"/>
+ <fsummary>Returns the smallest integer not less than the argument</fsummary>
+ <desc>
+ <p>Returns the smallest integer not less than
+ <c><anno>Number</anno></c>.
+ For example:</p>
+ <pre>
+> <input>ceil(5.5).</input>
+6</pre>
+ <p>Allowed in guard tests.</p>
+ </desc>
+ </func>
+ <func>
<name name="check_old_code" arity="1"/>
<fsummary>Check if a module has old code.</fsummary>
<desc>
@@ -1465,6 +1478,20 @@ true</pre>
</func>
<func>
+ <name name="floor" arity="1"/>
+ <fsummary>Returns the largest integer not greater than the argument</fsummary>
+ <desc>
+ <p>Returns the largest integer not greater than
+ <c><anno>Number</anno></c>.
+ For example:</p>
+ <pre>
+> <input>floor(-10.5).</input>
+-11</pre>
+ <p>Allowed in guard tests.</p>
+ </desc>
+ </func>
+
+ <func>
<name name="fun_info" arity="1"/>
<fsummary>Information about a fun.</fsummary>
<desc>
diff --git a/erts/emulator/beam/bif.tab b/erts/emulator/beam/bif.tab
index 7a35c02934..0bd80ea684 100644
--- a/erts/emulator/beam/bif.tab
+++ b/erts/emulator/beam/bif.tab
@@ -659,6 +659,15 @@ bif erlang:has_prepared_code_on_load/1
bif maps:take/2
#
+# New in 20.0
+#
+
+gcbif erlang:floor/1
+gcbif erlang:ceil/1
+bif math:floor/1
+bif math:ceil/1
+
+#
# Obsolete
#
diff --git a/erts/emulator/beam/erl_bif_guard.c b/erts/emulator/beam/erl_bif_guard.c
index b42d2dc28b..458315f293 100644
--- a/erts/emulator/beam/erl_bif_guard.c
+++ b/erts/emulator/beam/erl_bif_guard.c
@@ -141,6 +141,39 @@ BIF_RETTYPE trunc_1(BIF_ALIST_1)
BIF_RET(res);
}
+BIF_RETTYPE floor_1(BIF_ALIST_1)
+{
+ Eterm res;
+ FloatDef f;
+
+ if (is_not_float(BIF_ARG_1)) {
+ if (is_integer(BIF_ARG_1))
+ BIF_RET(BIF_ARG_1);
+ BIF_ERROR(BIF_P, BADARG);
+ }
+ GET_DOUBLE(BIF_ARG_1, f);
+ res = double_to_integer(BIF_P, floor(f.fd));
+ BIF_RET(res);
+}
+
+BIF_RETTYPE ceil_1(BIF_ALIST_1)
+{
+ Eterm res;
+ FloatDef f;
+
+ /* check arg */
+ if (is_not_float(BIF_ARG_1)) {
+ if (is_integer(BIF_ARG_1))
+ BIF_RET(BIF_ARG_1);
+ BIF_ERROR(BIF_P, BADARG);
+ }
+ /* get the float */
+ GET_DOUBLE(BIF_ARG_1, f);
+
+ res = double_to_integer(BIF_P, ceil(f.fd));
+ BIF_RET(res);
+}
+
BIF_RETTYPE round_1(BIF_ALIST_1)
{
Eterm res;
@@ -621,6 +654,38 @@ Eterm erts_gc_trunc_1(Process* p, Eterm* reg, Uint live)
reg, live);
}
+Eterm erts_gc_floor_1(Process* p, Eterm* reg, Uint live)
+{
+ Eterm arg;
+ FloatDef f;
+
+ arg = reg[live];
+ if (is_not_float(arg)) {
+ if (is_integer(arg)) {
+ return arg;
+ }
+ BIF_ERROR(p, BADARG);
+ }
+ GET_DOUBLE(arg, f);
+ return gc_double_to_integer(p, floor(f.fd), reg, live);
+}
+
+Eterm erts_gc_ceil_1(Process* p, Eterm* reg, Uint live)
+{
+ Eterm arg;
+ FloatDef f;
+
+ arg = reg[live];
+ if (is_not_float(arg)) {
+ if (is_integer(arg)) {
+ return arg;
+ }
+ BIF_ERROR(p, BADARG);
+ }
+ GET_DOUBLE(arg, f);
+ return gc_double_to_integer(p, ceil(f.fd), reg, live);
+}
+
static Eterm
gc_double_to_integer(Process* p, double x, Eterm* reg, Uint live)
{
diff --git a/erts/emulator/beam/erl_math.c b/erts/emulator/beam/erl_math.c
index fc0aaed18a..990fa63bd4 100644
--- a/erts/emulator/beam/erl_math.c
+++ b/erts/emulator/beam/erl_math.c
@@ -247,6 +247,12 @@ BIF_RETTYPE math_pow_2(BIF_ALIST_2)
return math_call_2(BIF_P, pow, BIF_ARG_1, BIF_ARG_2);
}
+BIF_RETTYPE math_ceil_1(BIF_ALIST_1)
+{
+ return math_call_1(BIF_P, ceil, BIF_ARG_1);
+}
-
-
+BIF_RETTYPE math_floor_1(BIF_ALIST_1)
+{
+ return math_call_1(BIF_P, floor, BIF_ARG_1);
+}
diff --git a/erts/emulator/test/num_bif_SUITE.erl b/erts/emulator/test/num_bif_SUITE.erl
index d1c9648017..1a1ab0e5e0 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, [],
@@ -295,30 +297,78 @@ t_round(Config) when is_list(Config) ->
-4294967297 = -round(id(4294967296.9)),
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.
+ t_trunc_and_friends_rand(100),
ok.
+t_trunc_and_friends_rand(0) ->
+ ok;
+t_trunc_and_friends_rand(N) ->
+ F0 = rand:uniform() * math:pow(10, 50*rand:normal()),
+ F = case rand:uniform() of
+ U when U < 0.5 -> -F0;
+ _ -> F0
+ end,
+ _ = trunc_and_friends(F),
+ 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.
diff --git a/erts/preloaded/ebin/erlang.beam b/erts/preloaded/ebin/erlang.beam
index c68debeabc..72c26a6b67 100644
--- a/erts/preloaded/ebin/erlang.beam
+++ b/erts/preloaded/ebin/erlang.beam
Binary files differ
diff --git a/erts/preloaded/src/erlang.erl b/erts/preloaded/src/erlang.erl
index 652a954807..5bd73fe44d 100644
--- a/erts/preloaded/src/erlang.erl
+++ b/erts/preloaded/src/erlang.erl
@@ -100,7 +100,8 @@
-export([binary_to_list/3, binary_to_term/1, binary_to_term/2]).
-export([bit_size/1, bitsize/1, bitstring_to_list/1]).
-export([bump_reductions/1, byte_size/1, call_on_load_function/1]).
--export([cancel_timer/1, cancel_timer/2, check_old_code/1, check_process_code/2,
+-export([cancel_timer/1, cancel_timer/2, ceil/1,
+ check_old_code/1, check_process_code/2,
check_process_code/3, crc32/1]).
-export([crc32/2, crc32_combine/3, date/0, decode_packet/3]).
-export([delete_element/2]).
@@ -109,7 +110,7 @@
-export([error/1, error/2, exit/1, exit/2, external_size/1]).
-export([external_size/2, finish_after_on_load/2, finish_loading/1, float/1]).
-export([float_to_binary/1, float_to_binary/2,
- float_to_list/1, float_to_list/2]).
+ float_to_list/1, float_to_list/2, floor/1]).
-export([fun_info/2, fun_info_mfa/1, fun_to_list/1, function_exported/3]).
-export([garbage_collect/0, garbage_collect/1, garbage_collect/2]).
-export([garbage_collect_message_area/0, get/0, get/1, get_keys/0, get_keys/1]).
@@ -474,6 +475,13 @@ cancel_timer(_TimerRef) ->
cancel_timer(_TimerRef, _Options) ->
erlang:nif_error(undefined).
+%% ceil/1
+%% Shadowed by erl_bif_types: erlang:ceil/1
+-spec ceil(Number) -> integer() when
+ Number :: number().
+ceil(_) ->
+ erlang:nif_error(undef).
+
%% check_old_code/1
-spec check_old_code(Module) -> boolean() when
Module :: module().
@@ -837,6 +845,13 @@ float_to_list(_Float) ->
float_to_list(_Float, _Options) ->
erlang:nif_error(undefined).
+%% floor/1
+%% Shadowed by erl_bif_types: erlang:floor/1
+-spec floor(Number) -> integer() when
+ Number :: number().
+floor(_) ->
+ erlang:nif_error(undef).
+
%% fun_info/2
-spec erlang:fun_info(Fun, Item) -> {Item, Info} when
Fun :: function(),
diff --git a/lib/compiler/src/beam_type.erl b/lib/compiler/src/beam_type.erl
index acaf3ede66..b4776294be 100644
--- a/lib/compiler/src/beam_type.erl
+++ b/lib/compiler/src/beam_type.erl
@@ -592,6 +592,8 @@ is_math_bif(log10, 1) -> true;
is_math_bif(sqrt, 1) -> true;
is_math_bif(atan2, 2) -> true;
is_math_bif(pow, 2) -> true;
+is_math_bif(ceil, 1) -> true;
+is_math_bif(floor, 1) -> true;
is_math_bif(pi, 0) -> true;
is_math_bif(_, _) -> false.
diff --git a/lib/compiler/src/beam_validator.erl b/lib/compiler/src/beam_validator.erl
index 4c0cb6780a..61aea57906 100644
--- a/lib/compiler/src/beam_validator.erl
+++ b/lib/compiler/src/beam_validator.erl
@@ -1506,7 +1506,9 @@ bif_type(abs, [Num], Vst) ->
bif_type(float, _, _) -> {float,[]};
bif_type('/', _, _) -> {float,[]};
%% Integer operations.
+bif_type(ceil, [_], _) -> {integer,[]};
bif_type('div', [_,_], _) -> {integer,[]};
+bif_type(floor, [_], _) -> {integer,[]};
bif_type('rem', [_,_], _) -> {integer,[]};
bif_type(length, [_], _) -> {integer,[]};
bif_type(size, [_], _) -> {integer,[]};
@@ -1640,6 +1642,8 @@ return_type_math(log10, 1) -> {float,[]};
return_type_math(sqrt, 1) -> {float,[]};
return_type_math(atan2, 2) -> {float,[]};
return_type_math(pow, 2) -> {float,[]};
+return_type_math(ceil, 1) -> {float,[]};
+return_type_math(floor, 1) -> {float,[]};
return_type_math(pi, 0) -> {float,[]};
return_type_math(F, A) when is_atom(F), is_integer(A), A >= 0 -> term.
diff --git a/lib/compiler/src/erl_bifs.erl b/lib/compiler/src/erl_bifs.erl
index 6b2d781a76..7693daaa56 100644
--- a/lib/compiler/src/erl_bifs.erl
+++ b/lib/compiler/src/erl_bifs.erl
@@ -75,10 +75,12 @@ is_pure(erlang, binary_to_list, 1) -> true;
is_pure(erlang, binary_to_list, 3) -> true;
is_pure(erlang, bit_size, 1) -> true;
is_pure(erlang, byte_size, 1) -> true;
+is_pure(erlang, ceil, 1) -> true;
is_pure(erlang, element, 2) -> true;
is_pure(erlang, float, 1) -> true;
is_pure(erlang, float_to_list, 1) -> true;
is_pure(erlang, float_to_binary, 1) -> true;
+is_pure(erlang, floor, 1) -> true;
is_pure(erlang, hash, 2) -> false;
is_pure(erlang, hd, 1) -> true;
is_pure(erlang, integer_to_binary, 1) -> true;
@@ -129,11 +131,13 @@ is_pure(math, asinh, 1) -> true;
is_pure(math, atan, 1) -> true;
is_pure(math, atan2, 2) -> true;
is_pure(math, atanh, 1) -> true;
+is_pure(math, ceil, 1) -> true;
is_pure(math, cos, 1) -> true;
is_pure(math, cosh, 1) -> true;
is_pure(math, erf, 1) -> true;
is_pure(math, erfc, 1) -> true;
is_pure(math, exp, 1) -> true;
+is_pure(math, floor, 1) -> true;
is_pure(math, log, 1) -> true;
is_pure(math, log2, 1) -> true;
is_pure(math, log10, 1) -> true;
diff --git a/lib/compiler/src/sys_core_fold.erl b/lib/compiler/src/sys_core_fold.erl
index e0de50f3ae..b8065176a3 100644
--- a/lib/compiler/src/sys_core_fold.erl
+++ b/lib/compiler/src/sys_core_fold.erl
@@ -2949,7 +2949,9 @@ returns_integer(bit_size, [_]) -> true;
returns_integer('bsl', [_,_]) -> true;
returns_integer('bsr', [_,_]) -> true;
returns_integer(byte_size, [_]) -> true;
+returns_integer(ceil, [_]) -> true;
returns_integer('div', [_,_]) -> true;
+returns_integer(floor, [_]) -> true;
returns_integer(length, [_]) -> true;
returns_integer('rem', [_,_]) -> true;
returns_integer('round', [_]) -> true;
diff --git a/lib/compiler/test/bif_SUITE.erl b/lib/compiler/test/bif_SUITE.erl
index 6d7231b426..6bde2f1da9 100644
--- a/lib/compiler/test/bif_SUITE.erl
+++ b/lib/compiler/test/bif_SUITE.erl
@@ -67,9 +67,9 @@ food(Curriculum) ->
0
end, Curriculum].
-%% Test trunc/1, round/1.
+%% Test trunc/1, round/1, floor/1, ceil/1.
trunc_and_friends(_Config) ->
- Bifs = [trunc,round],
+ Bifs = [trunc,round,floor,ceil],
Fs = trunc_and_friends_1(Bifs),
Mod = ?FUNCTION_NAME,
Calls = [begin
diff --git a/lib/compiler/test/float_SUITE.erl b/lib/compiler/test/float_SUITE.erl
index f6095947ca..0ebc71eb9b 100644
--- a/lib/compiler/test/float_SUITE.erl
+++ b/lib/compiler/test/float_SUITE.erl
@@ -150,6 +150,11 @@ math_functions(Config) when is_list(Config) ->
?OPTIONAL(0.0, math:erf(id(0))),
?OPTIONAL(1.0, math:erfc(id(0))),
+ 5.0 = math:floor(5.6),
+ 6.0 = math:ceil(5.6),
+ 5.0 = math:floor(id(5.4)),
+ 6.0 = math:ceil(id(5.4)),
+
%% Only for coverage (of beam_type.erl).
{'EXIT',{undef,_}} = (catch math:fnurfla(0)),
{'EXIT',{undef,_}} = (catch math:fnurfla(0, 0)),
diff --git a/lib/hipe/cerl/erl_bif_types.erl b/lib/hipe/cerl/erl_bif_types.erl
index 9453ca6c6f..32d5d39460 100644
--- a/lib/hipe/cerl/erl_bif_types.erl
+++ b/lib/hipe/cerl/erl_bif_types.erl
@@ -560,6 +560,9 @@ type(erlang, byte_size, 1, Xs, Opaques) ->
strict(erlang, byte_size, 1, Xs,
fun (_) -> t_non_neg_integer() end, Opaques);
%% Guard bif, needs to be here.
+type(erlang, ceil, 1, Xs, Opaques) ->
+ strict(erlang, ceil, 1, Xs, fun (_) -> t_integer() end, Opaques);
+%% Guard bif, needs to be here.
%% Also much more expressive than anything you could write in a spec...
type(erlang, element, 2, Xs, Opaques) ->
strict(erlang, element, 2, Xs,
@@ -588,6 +591,9 @@ type(erlang, element, 2, Xs, Opaques) ->
type(erlang, float, 1, Xs, Opaques) ->
strict(erlang, float, 1, Xs, fun (_) -> t_float() end, Opaques);
%% Guard bif, needs to be here.
+type(erlang, floor, 1, Xs, Opaques) ->
+ strict(erlang, floor, 1, Xs, fun (_) -> t_integer() end, Opaques);
+%% Guard bif, needs to be here.
type(erlang, hd, 1, Xs, Opaques) ->
strict(erlang, hd, 1, Xs, fun ([X]) -> t_cons_hd(X) end, Opaques);
type(erlang, info, 1, Xs, _) -> type(erlang, system_info, 1, Xs); % alias
@@ -2341,6 +2347,9 @@ arg_types(erlang, bit_size, 1) ->
%% Guard bif, needs to be here.
arg_types(erlang, byte_size, 1) ->
[t_bitstr()];
+%% Guard bif, needs to be here.
+arg_types(erlang, ceil, 1) ->
+ [t_number()];
arg_types(erlang, halt, 0) ->
[];
arg_types(erlang, halt, 1) ->
@@ -2361,6 +2370,9 @@ arg_types(erlang, element, 2) ->
arg_types(erlang, float, 1) ->
[t_number()];
%% Guard bif, needs to be here.
+arg_types(erlang, floor, 1) ->
+ [t_number()];
+%% Guard bif, needs to be here.
arg_types(erlang, hd, 1) ->
[t_cons()];
arg_types(erlang, info, 1) ->
diff --git a/lib/stdlib/doc/src/math.xml b/lib/stdlib/doc/src/math.xml
index 1358ce5cbf..70ca6ae78e 100644
--- a/lib/stdlib/doc/src/math.xml
+++ b/lib/stdlib/doc/src/math.xml
@@ -57,9 +57,11 @@
<name name="atan" arity="1"/>
<name name="atan2" arity="2"/>
<name name="atanh" arity="1"/>
+ <name name="ceil" arity="1"/>
<name name="cos" arity="1"/>
<name name="cosh" arity="1"/>
<name name="exp" arity="1"/>
+ <name name="floor" arity="1"/>
<name name="log" arity="1"/>
<name name="log10" arity="1"/>
<name name="log2" arity="1"/>
diff --git a/lib/stdlib/src/erl_internal.erl b/lib/stdlib/src/erl_internal.erl
index 5d6aa0ebe8..006e7946af 100644
--- a/lib/stdlib/src/erl_internal.erl
+++ b/lib/stdlib/src/erl_internal.erl
@@ -69,8 +69,10 @@ guard_bif(binary_part, 2) -> true;
guard_bif(binary_part, 3) -> true;
guard_bif(bit_size, 1) -> true;
guard_bif(byte_size, 1) -> true;
+guard_bif(ceil, 1) -> true;
guard_bif(element, 2) -> true;
guard_bif(float, 1) -> true;
+guard_bif(floor, 1) -> true;
guard_bif(hd, 1) -> true;
guard_bif(length, 1) -> true;
guard_bif(map_size, 1) -> true;
@@ -258,6 +260,7 @@ bif(bitsize, 1) -> true;
bif(bit_size, 1) -> true;
bif(bitstring_to_list, 1) -> true;
bif(byte_size, 1) -> true;
+bif(ceil, 1) -> true;
bif(check_old_code, 1) -> true;
bif(check_process_code, 2) -> true;
bif(check_process_code, 3) -> true;
@@ -278,6 +281,7 @@ bif(float_to_list, 1) -> true;
bif(float_to_list, 2) -> true;
bif(float_to_binary, 1) -> true;
bif(float_to_binary, 2) -> true;
+bif(floor, 1) -> true;
bif(garbage_collect, 0) -> true;
bif(garbage_collect, 1) -> true;
bif(garbage_collect, 2) -> true;
diff --git a/lib/stdlib/src/math.erl b/lib/stdlib/src/math.erl
index 97c965e27a..1db48cd0a2 100644
--- a/lib/stdlib/src/math.erl
+++ b/lib/stdlib/src/math.erl
@@ -25,7 +25,8 @@
-export([sin/1, cos/1, tan/1, asin/1, acos/1, atan/1, atan2/2, sinh/1,
cosh/1, tanh/1, asinh/1, acosh/1, atanh/1, exp/1, log/1,
- log2/1, log10/1, pow/2, sqrt/1, erf/1, erfc/1]).
+ log2/1, log10/1, pow/2, sqrt/1, erf/1, erfc/1,
+ ceil/1, floor/1]).
-spec acos(X) -> float() when
X :: number().
@@ -63,6 +64,11 @@ atan2(_, _) ->
atanh(_) ->
erlang:nif_error(undef).
+-spec ceil(X) -> float() when
+ X :: number().
+ceil(_) ->
+ erlang:nif_error(undef).
+
-spec cos(X) -> float() when
X :: number().
cos(_) ->
@@ -88,6 +94,11 @@ erfc(_) ->
exp(_) ->
erlang:nif_error(undef).
+-spec floor(X) -> float() when
+ X :: number().
+floor(_) ->
+ erlang:nif_error(undef).
+
-spec log(X) -> float() when
X :: number().
log(_) ->
diff --git a/lib/stdlib/test/Makefile b/lib/stdlib/test/Makefile
index 28c35aed55..deac04aa66 100644
--- a/lib/stdlib/test/Makefile
+++ b/lib/stdlib/test/Makefile
@@ -52,6 +52,7 @@ MODULES= \
io_proto_SUITE \
lists_SUITE \
log_mf_h_SUITE \
+ math_SUITE \
ms_transform_SUITE \
proc_lib_SUITE \
qlc_SUITE \
diff --git a/lib/stdlib/test/math_SUITE.erl b/lib/stdlib/test/math_SUITE.erl
new file mode 100644
index 0000000000..2b29e44228
--- /dev/null
+++ b/lib/stdlib/test/math_SUITE.erl
@@ -0,0 +1,92 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2007-2016. 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%
+%%
+
+-module(math_SUITE).
+
+-include_lib("common_test/include/ct.hrl").
+
+%% Test server specific exports
+-export([all/0, suite/0,groups/0,init_per_suite/1, end_per_suite/1,
+ init_per_group/2,end_per_group/2,
+ init_per_testcase/2, end_per_testcase/2]).
+
+%% Test cases
+-export([floor_ceil/1]).
+
+
+suite() ->
+ [{ct_hooks,[ts_install_cth]},
+ {timetrap,{minutes,1}}].
+
+all() ->
+ [floor_ceil].
+
+groups() ->
+ [].
+
+init_per_suite(Config) ->
+ Config.
+
+end_per_suite(_Config) ->
+ ok.
+
+init_per_group(_GroupName, Config) ->
+ Config.
+
+end_per_group(_GroupName, Config) ->
+ Config.
+
+
+init_per_testcase(_Case, Config) ->
+ Config.
+
+end_per_testcase(_Case, _Config) ->
+ ok.
+
+floor_ceil(_Config) ->
+ MinusZero = 0.0/(-1.0),
+ -43.0 = do_floor_ceil(-42.1),
+ -43.0 = do_floor_ceil(-42.7),
+ 0.0 = do_floor_ceil(MinusZero),
+ 10.0 = do_floor_ceil(10.1),
+ 10.0 = do_floor_ceil(10.9),
+
+ -533.0 = do_floor_ceil(-533.0),
+ 453555.0 = do_floor_ceil(453555.0),
+
+ -58.0 = do_floor_ceil(-58),
+ 777.0 = do_floor_ceil(777),
+
+ ok.
+
+do_floor_ceil(Val) ->
+ Floor = math:floor(Val),
+ Ceil = math:ceil(Val),
+
+ true = is_float(Floor),
+ true = is_float(Ceil),
+
+ if
+ Floor =:= Ceil ->
+ Floor;
+ true ->
+ 1.0 = Ceil - Floor,
+ Floor
+ end.
diff --git a/lib/tools/emacs/erlang.el b/lib/tools/emacs/erlang.el
index 73c6b8d768..a0f9512c15 100644
--- a/lib/tools/emacs/erlang.el
+++ b/lib/tools/emacs/erlang.el
@@ -743,6 +743,7 @@ resulting regexp is surrounded by \\_< and \\_>."
"bitsize"
"bitstring_to_list"
"byte_size"
+ "ceil"
"check_old_code"
"check_process_code"
"date"
@@ -753,6 +754,7 @@ resulting regexp is surrounded by \\_< and \\_>."
"erase"
"error"
"exit"
+ "floor"
"float"
"float_to_binary"
"float_to_list"