From a8f9ae096c7458a1304a80cf7aea119729cd6293 Mon Sep 17 00:00:00 2001 From: dajiaohuang Date: Fri, 18 Sep 2026 02:05:01 +0800 Subject: [PATCH] Match Erlang semantics for div/2 and round/1 Two functions in the erlang compatibility layer diverge from Erlang on negative operands: - div/2 used `/`, so div(-7, 2) returned -3.5 instead of -3. Erlang's div truncates toward zero. - round/1 used Math.round, which rounds half values toward +Infinity, so round(-2.5) returned -2 instead of -3, and round(-0.5) returned -0 instead of -1. Erlang rounds half values away from zero. Both are reachable from compiled Elixir: div(-7, 2) and round(-2.5) compile to Core.erlang.div and Core.erlang.round calls. Also drop a leftover console.log in nodes/1 that printed the accumulator on every call. Add tests for div, rem, round and trunc covering negative operands. --- .../lib/core/erlang_compat/erlang.js | 5 ++-- .../tests/core/erlang_compat/erlang_spec.js | 30 +++++++++++++++++++ 2 files changed, 32 insertions(+), 3 deletions(-) diff --git a/src/javascript/lib/core/erlang_compat/erlang.js b/src/javascript/lib/core/erlang_compat/erlang.js index ddece09d..a72d3805 100644 --- a/src/javascript/lib/core/erlang_compat/erlang.js +++ b/src/javascript/lib/core/erlang_compat/erlang.js @@ -164,7 +164,7 @@ function equals(left, right) { } function div(left, right) { - return left / right; + return Math.trunc(left / right); } function not(x) { @@ -357,7 +357,7 @@ function min(first, second) { } function round(number) { - return Math.round(number); + return Math.sign(number) * Math.round(Math.abs(number)); } function tl(list) { @@ -463,7 +463,6 @@ function nodes(arg = []) { for (const nodeType of nodeTypes) { if (nodeType === Symbol.for('this')) { nodesFound.push(Symbol.for('nonode@nohost')); - console.log(nodesFound); } } return nodesFound; diff --git a/src/javascript/tests/core/erlang_compat/erlang_spec.js b/src/javascript/tests/core/erlang_compat/erlang_spec.js index 6e41e6ea..bc2c243d 100644 --- a/src/javascript/tests/core/erlang_compat/erlang_spec.js +++ b/src/javascript/tests/core/erlang_compat/erlang_spec.js @@ -83,6 +83,36 @@ test('list_subtraction', (t) => { t.deepEqual(Core.erlang.list_subtraction([1, 2, 3], [1, 2]), [3]); }); +test('div', (t) => { + t.is(Core.erlang.div(6, 3), 2); + t.is(Core.erlang.div(7, 2), 3); + t.is(Core.erlang.div(-7, 2), -3); + t.is(Core.erlang.div(7, -2), -3); + t.is(Core.erlang.div(-7, -2), 3); +}); + +test('rem', (t) => { + t.is(Core.erlang.rem(7, 2), 1); + t.is(Core.erlang.rem(-7, 2), -1); + t.is(Core.erlang.rem(7, -2), 1); + t.is(Core.erlang.rem(-7, -2), -1); +}); + +test('round', (t) => { + t.is(Core.erlang.round(1.4), 1); + t.is(Core.erlang.round(2.5), 3); + t.is(Core.erlang.round(-2.5), -3); + t.is(Core.erlang.round(0.5), 1); + t.is(Core.erlang.round(-0.5), -1); + t.is(Core.erlang.round(4), 4); + t.is(Core.erlang.round(-4), -4); +}); + +test('trunc', (t) => { + t.is(Core.erlang.trunc(2.7), 2); + t.is(Core.erlang.trunc(-2.7), -2); +}); + test('node', (t) => { t.deepEqual(Core.erlang.node(), Symbol.for('nonode@nohost')); });