From c5c4913bdaee4702e8c5e173224b86a587780c1e Mon Sep 17 00:00:00 2001 From: Sam Hocevar Date: Sun, 2 Oct 2011 23:36:31 +0000 Subject: [PATCH] core: implement round() and fmod() for real numbers. --- src/real.cpp | 20 +++++++++++++++++++ src/real.h | 2 ++ test/unit/real.cpp | 49 ++++++++++++++++++++++++---------------------- 3 files changed, 48 insertions(+), 23 deletions(-) diff --git a/src/real.cpp b/src/real.cpp index ff8579e5..35b2b604 100644 --- a/src/real.cpp +++ b/src/real.cpp @@ -685,6 +685,26 @@ real ceil(real const &x) return ret + real::R_1; } +real round(real const &x) +{ + if (x < real::R_0) + return -round(-x); + + return floor(x + (real::R_1 >> 1)); +} + +real fmod(real const &x, real const &y) +{ + if (!y) + return real::R_0; /* FIXME: return NaN */ + + if (!x) + return x; + + real tmp = round(x / y); + return x - tmp * y; +} + real sin(real const &x) { real ret = 0.0, fact = 1.0, xn = x, x2 = x * x; diff --git a/src/real.h b/src/real.h index e88707a5..c12738dc 100644 --- a/src/real.h +++ b/src/real.h @@ -71,6 +71,8 @@ public: friend real floor(real const &x); friend real ceil(real const &x); + friend real round(real const &x); + friend real fmod(real const &x, real const &y); friend real sin(real const &x); friend real cos(real const &x); diff --git a/test/unit/real.cpp b/test/unit/real.cpp index cf482789..93e17120 100644 --- a/test/unit/real.cpp +++ b/test/unit/real.cpp @@ -257,42 +257,45 @@ LOLUNIT_FIXTURE(RealTest) } } - LOLUNIT_TEST(FloorCeil) + LOLUNIT_TEST(FloorCeilEtc) { double tests[] = { - -2.0, -2.0, -2.0, - -1.5, -2.0, -1.0, - -1.0, -1.0, -1.0, - -0.0, -0.0, -0.0, - 0.0, 0.0, 0.0, - 0.25, 0.0, 1.0, - 0.375, 0.0, 1.0, - 0.5, 0.0, 1.0, - 1.0, 1.0, 1.0, - 1.5, 1.0, 2.0, - 2.0, 2.0, 2.0, - 2.5, 2.0, 3.0, - 3.0, 3.0, 3.0, - 8192.0, 8192.0, 8192.0, - 8192.03125, 8192.0, 8193.0, - 8192.5, 8192.0, 8193.0, - 8193.0, 8193.0, 8193.0, - 549755813888.0, 549755813888.0, 549755813888.0, - 549755813888.03125, 549755813888.0, 549755813889.0, - 549755813888.5, 549755813888.0, 549755813889.0, - 549755813889.0, 549755813889.0, 549755813889.0, + -2.0, -2.0, -2.0, -2.0, + -1.5, -2.0, -1.0, -2.0, + -1.0, -1.0, -1.0, -1.0, + -0.0, -0.0, -0.0, -0.0, + 0.0, 0.0, 0.0, 0.0, + 0.25, 0.0, 1.0, 0.0, + 0.375, 0.0, 1.0, 0.0, + 0.5, 0.0, 1.0, 1.0, + 1.0, 1.0, 1.0, 1.0, + 1.5, 1.0, 2.0, 2.0, + 2.0, 2.0, 2.0, 2.0, + 2.5, 2.0, 3.0, 3.0, + 3.0, 3.0, 3.0, 3.0, + 8192.0, 8192.0, 8192.0, 8192.0, + 8192.03125, 8192.0, 8193.0, 8192.0, + 8192.5, 8192.0, 8193.0, 8193.0, + 8193.0, 8193.0, 8193.0, 8193.0, + 549755813888.0, 549755813888.0, 549755813888.0, 549755813888.0, + 549755813888.03125, 549755813888.0, 549755813889.0, 549755813888.0, + 549755813888.5, 549755813888.0, 549755813889.0, 549755813889.0, + 549755813889.0, 549755813889.0, 549755813889.0, 549755813889.0, }; - for (unsigned int n = 0; n < sizeof(tests) / sizeof(*tests); n += 3) + for (unsigned int n = 0; n < sizeof(tests) / sizeof(*tests); n += 4) { double a0 = floor((real)tests[n]); double b0 = tests[n + 1]; double a1 = ceil((real)tests[n]); double b1 = tests[n + 2]; + double a2 = round((real)tests[n]); + double b2 = tests[n + 3]; LOLUNIT_ASSERT_EQUAL(b0, a0); LOLUNIT_ASSERT_EQUAL(b1, a1); + LOLUNIT_ASSERT_EQUAL(b2, a2); } } };