From a173e49ddc520dbe2e139f93f8217b91e206d277 Mon Sep 17 00:00:00 2001 From: Sam Hocevar Date: Thu, 22 Sep 2011 07:16:02 +0000 Subject: [PATCH] core: implement comparison operators for reals. --- src/real.cpp | 73 +++++++++++++++++++++++++++++++++++++++------- src/real.h | 5 ++++ test/unit/real.cpp | 21 +++++++++++++ 3 files changed, 89 insertions(+), 10 deletions(-) diff --git a/src/real.cpp b/src/real.cpp index f8e45579..548b409a 100644 --- a/src/real.cpp +++ b/src/real.cpp @@ -77,17 +77,19 @@ real real::operator +(real const &x) const if (x.m_signexp << 1 == 0) return *this; - /* Ensure *this is the larger exponent, and both arguments are - * positive (otherwise, switch signs, or replace + with -). */ - if ((m_signexp << 1) < (x.m_signexp << 1)) - return x + *this; - + /* Ensure both arguments are positive. Otherwise, switch signs, + * or replace + with -). */ if (m_signexp >> 31) return -(-*this + -x); if (x.m_signexp >> 31) return *this - x; + /* Ensure *this is the larger exponent (no need to be strictly larger, + * as in subtraction). Otherwise, switch. */ + if ((m_signexp << 1) < (x.m_signexp << 1)) + return x + *this; + real ret; int e1 = m_signexp - (1 << 30) + 1; @@ -137,17 +139,18 @@ real real::operator -(real const &x) const if (x.m_signexp << 1 == 0) return *this; - /* Ensure *this is the larger exponent, and both arguments are - * positive (otherwise, switch signs, or replace - with +). */ - if ((m_signexp << 1) < (x.m_signexp << 1)) - return -(x - *this); - + /* Ensure both arguments are positive. Otherwise, switch signs, + * or replace - with +). */ if (m_signexp >> 31) return -(-*this + x); if (x.m_signexp >> 31) return (*this) + (-x); + /* Ensure *this is larger than x */ + if (*this < x) + return -(x - *this); + real ret; return ret; @@ -202,6 +205,56 @@ real real::operator *(real const &x) const return ret; } +bool real::operator <(real const &x) const +{ + /* Ensure both numbers are positive */ + if (m_signexp >> 31) + return (x.m_signexp >> 31) ? -*this > -x : true; + + if (x.m_signexp >> 31) + return false; + + /* Compare all relevant bits */ + if (m_signexp != x.m_signexp) + return m_signexp < x.m_signexp; + + for (int i = 0; i < BIGITS; i++) + if (m_mantissa[i] != x.m_mantissa[i]) + return m_mantissa[i] < x.m_mantissa[i]; + + return false; +} + +bool real::operator <=(real const &x) const +{ + return !(*this > x); +} + +bool real::operator >(real const &x) const +{ + /* Ensure both numbers are positive */ + if (m_signexp >> 31) + return (x.m_signexp >> 31) ? -*this < -x : false; + + if (x.m_signexp >> 31) + return true; + + /* Compare all relevant bits */ + if (m_signexp != x.m_signexp) + return m_signexp > x.m_signexp; + + for (int i = 0; i < BIGITS; i++) + if (m_mantissa[i] != x.m_mantissa[i]) + return m_mantissa[i] > x.m_mantissa[i]; + + return false; +} + +bool real::operator >=(real const &x) const +{ + return !(*this < x); +} + void real::print() const { printf("%x %08x ", m_signexp >> 31, (m_signexp << 1) >> 1); diff --git a/src/real.h b/src/real.h index 94f27d58..315d0838 100644 --- a/src/real.h +++ b/src/real.h @@ -35,6 +35,11 @@ public: real operator -(real const &x) const; real operator *(real const &x) const; + bool operator <(real const &x) const; + bool operator >(real const &x) const; + bool operator <=(real const &x) const; + bool operator >=(real const &x) const; + void print() const; private: diff --git a/test/unit/real.cpp b/test/unit/real.cpp index 3fabc757..d84e49c7 100644 --- a/test/unit/real.cpp +++ b/test/unit/real.cpp @@ -50,6 +50,27 @@ LOLUNIT_FIXTURE(RealTest) LOLUNIT_ASSERT_EQUAL(a4, 0.0f); } + LOLUNIT_TEST(test_real_comp) + { + LOLUNIT_ASSERT(real(1.0f) > real(0.5f)); + LOLUNIT_ASSERT(real(1.0f) >= real(0.5f)); + LOLUNIT_ASSERT(real(1.0f) >= real(1.0f)); + + LOLUNIT_ASSERT(real(-1.0f) < real(-0.5f)); + LOLUNIT_ASSERT(real(-1.0f) <= real(-0.5f)); + LOLUNIT_ASSERT(real(-1.0f) <= real(-1.0f)); + + LOLUNIT_ASSERT(real(-1.0f) < real(0.5f)); + LOLUNIT_ASSERT(real(-0.5f) < real(1.0f)); + LOLUNIT_ASSERT(real(-1.0f) <= real(0.5f)); + LOLUNIT_ASSERT(real(-0.5f) <= real(1.0f)); + + LOLUNIT_ASSERT(real(1.0f) > real(-0.5f)); + LOLUNIT_ASSERT(real(0.5f) > real(-1.0f)); + LOLUNIT_ASSERT(real(1.0f) >= real(-0.5f)); + LOLUNIT_ASSERT(real(0.5f) >= real(-1.0f)); + } + LOLUNIT_TEST(test_real_add) { float a1 = real(1.0f) + real(0.0f);