From 1ea2d884d2231ce6b6b4abd5d4e25e0ae55d9a3d Mon Sep 17 00:00:00 2001 From: Yuval Tassa Date: Sun, 5 Jul 2026 10:47:30 -0700 Subject: [PATCH] Change mju_round to use standard round() function. PiperOrigin-RevId: 942873144 Change-Id: I3fd0d630643c104ff464d619387ff36582c2a5d8 --- doc/changelog.rst | 2 ++ src/engine/engine_util_misc.c | 14 +++++--------- test/engine/engine_util_misc_test.cc | 24 ++++++++++++++++++++++++ 3 files changed, 31 insertions(+), 9 deletions(-) diff --git a/doc/changelog.rst b/doc/changelog.rst index 0b450ead..e7bbc3a5 100644 --- a/doc/changelog.rst +++ b/doc/changelog.rst @@ -27,6 +27,8 @@ General ``(nv x nC)``. - Removed the legacy sparse ancestor-walk inertia matrix ``mjData.qM``. The joint-space inertia matrix is now stored exclusively in the compressed sparse row (CSR) format ``mjData.M``. + - :ref:`mju_round` now breaks ties away from zero rather than towards :math:`+\infty`. This only affects + negative half-integers, e.g. ``mju_round(-2.5)`` now returns -3 rather than -2. Version 3.10.0 (June 22, 2026) ------------------------------ diff --git a/src/engine/engine_util_misc.c b/src/engine/engine_util_misc.c index 3c438ba7..5242d040 100644 --- a/src/engine/engine_util_misc.c +++ b/src/engine/engine_util_misc.c @@ -15,13 +15,13 @@ #include "engine/engine_util_misc.h" #include +#include #include #include #include #include #include -#include #include #include #include "engine/engine_array_safety.h" @@ -1762,14 +1762,10 @@ mjtNum mju_sign(mjtNum x) { // round to nearest integer int mju_round(mjtNum x) { - mjtNum lower = floor(x); - mjtNum upper = ceil(x); - - if (x-lower < upper-x) { - return (int)lower; - } else { - return (int)upper; - } + double d = (double)x; + if (d > INT_MAX) return INT_MAX; + if (d < INT_MIN) return INT_MIN; + return (int)round(d); } diff --git a/test/engine/engine_util_misc_test.cc b/test/engine/engine_util_misc_test.cc index ec1b457f..88b6b778 100644 --- a/test/engine/engine_util_misc_test.cc +++ b/test/engine/engine_util_misc_test.cc @@ -17,6 +17,7 @@ #include "src/engine/engine_util_misc.h" #include +#include #include #include #include @@ -1720,5 +1721,28 @@ TEST_F(ShellTFITest, NoInteriorSmallGrid) { } } +TEST_F(UtilMiscTest, Round) { + // basic rounding + EXPECT_EQ(mju_round(2.3), 2); + EXPECT_EQ(mju_round(2.7), 3); + EXPECT_EQ(mju_round(-2.3), -2); + EXPECT_EQ(mju_round(-2.7), -3); + + // exact integers + EXPECT_EQ(mju_round(0.0), 0); + EXPECT_EQ(mju_round(3.0), 3); + EXPECT_EQ(mju_round(-3.0), -3); + + // ties: round() rounds away from zero + EXPECT_EQ(mju_round(0.5), 1); + EXPECT_EQ(mju_round(1.5), 2); + EXPECT_EQ(mju_round(-0.5), -1); + EXPECT_EQ(mju_round(-1.5), -2); + + // overflow clamps to INT_MAX/INT_MIN + EXPECT_EQ(mju_round(1e18), INT_MAX); + EXPECT_EQ(mju_round(-1e18), INT_MIN); +} + } // namespace } // namespace mujoco