Skip to content

Commit d0207c1

Browse files
FKubisSWMjgonet
authored andcommitted
Implement fdiv bif for erlang://2
Signed-off-by: Jakub Gonet <jakub.gonet@swmansion.com>
1 parent 542d36b commit d0207c1

File tree

6 files changed

+81
-1
lines changed

6 files changed

+81
-1
lines changed

src/libAtomVM/bif.c

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -861,6 +861,35 @@ term bif_erlang_mul_2(Context *ctx, uint32_t fail_label, int live, term arg1, te
861861
}
862862
}
863863

864+
term bif_erlang_fdiv_2(Context *ctx, uint32_t fail_label, int live, term arg1, term arg2)
865+
{
866+
UNUSED(live);
867+
if (!term_is_integer(arg1) && !term_is_float(arg1)) {
868+
TRACE("error: arg1: 0x%lx, arg2: 0x%lx\n", arg1, arg2);
869+
RAISE_ERROR_BIF(fail_label, BADARITH_ATOM);
870+
}
871+
872+
if (!term_is_integer(arg2) && !term_is_float(arg2)) {
873+
TRACE("error: arg1: 0x%lx, arg2: 0x%lx\n", arg1, arg2);
874+
RAISE_ERROR_BIF(fail_label, BADARITH_ATOM);
875+
}
876+
avm_float_t farg1 = term_conv_to_float(arg1);
877+
avm_float_t farg2 = term_conv_to_float(arg2);
878+
879+
if (UNLIKELY(farg2 == 0)) {
880+
RAISE_ERROR_BIF(fail_label, BADARITH_ATOM);
881+
}
882+
avm_float_t fresult = farg1 / farg2;
883+
884+
if (UNLIKELY(!isfinite(fresult))) {
885+
RAISE_ERROR_BIF(fail_label, BADARITH_ATOM);
886+
}
887+
if (UNLIKELY(memory_ensure_free_with_roots(ctx, FLOAT_SIZE, live, ctx->x, MEMORY_CAN_SHRINK) != MEMORY_GC_OK)) {
888+
RAISE_ERROR_BIF(fail_label, OUT_OF_MEMORY_ATOM);
889+
}
890+
return term_from_float(fresult, &ctx->heap);
891+
}
892+
864893
static term div_boxed_helper(Context *ctx, uint32_t fail_label, uint32_t live, term arg1, term arg2)
865894
{
866895
int size = 0;

src/libAtomVM/bif.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,7 @@ term bif_erlang_add_2(Context *ctx, uint32_t fail_label, int live, term arg1, te
8181
term bif_erlang_plus_1(Context *ctx, uint32_t fail_label, int live, term arg1);
8282
term bif_erlang_sub_2(Context *ctx, uint32_t fail_label, int live, term arg1, term arg2);
8383
term bif_erlang_mul_2(Context *ctx, uint32_t fail_label, int live, term arg1, term arg2);
84+
term bif_erlang_fdiv_2(Context *ctx, uint32_t fail_label, int live, term arg1, term arg2);
8485
term bif_erlang_div_2(Context *ctx, uint32_t fail_label, int live, term arg1, term arg2);
8586
term bif_erlang_rem_2(Context *ctx, uint32_t fail_label, int live, term arg1, term arg2);
8687
term bif_erlang_neg_1(Context *ctx, uint32_t fail_label, int live, term arg1);

src/libAtomVM/bifs.gperf

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,7 @@ erlang:>=/2, {.bif.base.type = BIFFunctionType, .bif.bif2_ptr = bif_erlang_great
7474
erlang:+/2, {.gcbif.base.type = GCBIFFunctionType, .gcbif.gcbif2_ptr = bif_erlang_add_2}
7575
erlang:-/2, {.gcbif.base.type = GCBIFFunctionType, .gcbif.gcbif2_ptr = bif_erlang_sub_2}
7676
erlang:*/2, {.gcbif.base.type = GCBIFFunctionType, .gcbif.gcbif2_ptr = bif_erlang_mul_2}
77+
erlang://2, {.gcbif.base.type = GCBIFFunctionType, .gcbif.gcbif2_ptr = bif_erlang_fdiv_2}
7778
erlang:div/2, {.gcbif.base.type = GCBIFFunctionType, .gcbif.gcbif2_ptr = bif_erlang_div_2}
7879
erlang:rem/2, {.gcbif.base.type = GCBIFFunctionType, .gcbif.gcbif2_ptr = bif_erlang_rem_2}
7980
erlang:-/1, {.gcbif.base.type = GCBIFFunctionType, .gcbif.gcbif1_ptr = bif_erlang_neg_1}

tests/libs/estdlib/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@ set(ERLANG_MODULES
5050
test_lists_subtraction
5151
test_tcp_socket
5252
test_udp_socket
53+
test_bif_bin_arith_ops
5354
notify_init_server
5455
ping_pong_server
5556
)
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
%
2+
% This file is part of AtomVM.
3+
%
4+
% Copyright 2025 Jakub Gonet <jakub.gonet@swmansion.com>
5+
%
6+
% Licensed under the Apache License, Version 2.0 (the "License");
7+
% you may not use this file except in compliance with the License.
8+
% You may obtain a copy of the License at
9+
%
10+
% http://www.apache.org/licenses/LICENSE-2.0
11+
%
12+
% Unless required by applicable law or agreed to in writing, software
13+
% distributed under the License is distributed on an "AS IS" BASIS,
14+
% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15+
% See the License for the specific language governing permissions and
16+
% limitations under the License.
17+
%
18+
% SPDX-License-Identifier: Apache-2.0 OR LGPL-2.1-or-later
19+
%
20+
-module(test_bif_bin_arith_ops).
21+
22+
-define(ID(X), ?MODULE:id(X)).
23+
-export([test/0, id/1]).
24+
25+
test() ->
26+
Ops = ['+', '-', '*', '/'],
27+
ValidInputs = [[2, 3], [0, 2], [2.0, 3], [2, 3.0], [2.0, 3.0]],
28+
InvalidInputs = [[not_int, 1], [1, not_int]],
29+
[{ok, _} = call_op(Name, Args) || Name <- Ops, Args <- ValidInputs],
30+
[{error, badarith} = call_op(Name, Args) || Name <- Ops, Args <- InvalidInputs],
31+
32+
{ok, 0} = call_op('div', [2, 3]),
33+
{ok, 2} = call_op('rem', [2, 3]),
34+
{error, badarith} = call_op('div', [2.0, 3]),
35+
{error, badarith} = call_op('div', [2, 3.0]),
36+
{error, badarith} = call_op('rem', [2.0, 3]),
37+
{error, badarith} = call_op('rem', [2, 3.0]),
38+
ok.
39+
40+
call_op(Name, Args) ->
41+
try apply(erlang, ?ID(Name), ?ID(Args)) of
42+
V -> {ok, V}
43+
catch
44+
C:E -> {C, E}
45+
end.
46+
47+
id(X) -> X.

tests/libs/estdlib/tests.erl

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -75,7 +75,8 @@ get_non_networking_tests(_OTPVersion) ->
7575
test_timer,
7676
test_spawn,
7777
test_supervisor,
78-
test_lists_subtraction
78+
test_lists_subtraction,
79+
test_bif_bin_arith_ops
7980
].
8081

8182
get_networking_tests(OTPVersion) when

0 commit comments

Comments
 (0)