Skip to content

Commit bf6759c

Browse files
committed
Merge pull request #1707 from jgonet/jgonet/fdiv2
Implement BIF for number division Opcode's already handled, needed when division is called from dynamic call. These changes are made under both the "Apache 2.0" and the "GNU Lesser General Public License 2.1 or later" license terms (dual license). SPDX-License-Identifier: Apache-2.0 OR LGPL-2.1-or-later
2 parents 85d6714 + c1f00fc commit bf6759c

File tree

6 files changed

+80
-0
lines changed

6 files changed

+80
-0
lines changed

src/libAtomVM/bif.c

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -861,6 +861,32 @@ 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 (UNLIKELY(!term_is_number(arg1))) {
868+
RAISE_ERROR_BIF(fail_label, BADARITH_ATOM);
869+
}
870+
if (UNLIKELY(!term_is_number(arg2))) {
871+
RAISE_ERROR_BIF(fail_label, BADARITH_ATOM);
872+
}
873+
avm_float_t farg1 = term_conv_to_float(arg1);
874+
avm_float_t farg2 = term_conv_to_float(arg2);
875+
876+
if (UNLIKELY(farg2 == 0)) {
877+
RAISE_ERROR_BIF(fail_label, BADARITH_ATOM);
878+
}
879+
avm_float_t fresult = farg1 / farg2;
880+
881+
if (UNLIKELY(!isfinite(fresult))) {
882+
RAISE_ERROR_BIF(fail_label, BADARITH_ATOM);
883+
}
884+
if (UNLIKELY(memory_ensure_free_with_roots(ctx, FLOAT_SIZE, live, ctx->x, MEMORY_CAN_SHRINK) != MEMORY_GC_OK)) {
885+
RAISE_ERROR_BIF(fail_label, OUT_OF_MEMORY_ATOM);
886+
}
887+
return term_from_float(fresult, &ctx->heap);
888+
}
889+
864890
static term div_boxed_helper(Context *ctx, uint32_t fail_label, uint32_t live, term arg1, term arg2)
865891
{
866892
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/erlang_tests/CMakeLists.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -389,6 +389,7 @@ compile_erlang(floatabs)
389389
compile_erlang(floatdiv)
390390
compile_erlang(floatmath)
391391
compile_erlang(floatext)
392+
compile_erlang(bif_bin_arith_ops)
392393

393394
compile_erlang(boxed_is_not_float)
394395
compile_erlang(float_is_float)
@@ -880,6 +881,7 @@ add_custom_target(erlang_test_modules DEPENDS
880881
floatdiv.beam
881882
floatmath.beam
882883
floatext.beam
884+
bif_bin_arith_ops.beam
883885

884886
boxed_is_not_float.beam
885887
float_is_float.beam
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
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(bif_bin_arith_ops).
21+
22+
-define(ID(X), ?MODULE:id(X)).
23+
-export([start/0, id/1]).
24+
25+
start() ->
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+
0.
39+
40+
call_op(RawName, [RawA, RawB]) ->
41+
Name = ?ID(RawName),
42+
[A, B] = ?ID([RawA, RawB]),
43+
try erlang:Name(A, B) of
44+
V -> {ok, V}
45+
catch
46+
C:E -> {C, E}
47+
end.
48+
49+
id(X) -> X.

tests/test.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -458,6 +458,7 @@ struct Test tests[] = {
458458
TEST_CASE_EXPECTED(list2float, 511),
459459
TEST_CASE(floatmath),
460460
TEST_CASE(floatext),
461+
TEST_CASE(bif_bin_arith_ops),
461462

462463
TEST_CASE(test_fp_allocate_heap_zero),
463464

0 commit comments

Comments
 (0)