diff --git a/src/real.cpp b/src/real.cpp index 709d4082..f8e45579 100644 --- a/src/real.cpp +++ b/src/real.cpp @@ -53,7 +53,7 @@ real::operator float() const uint32_t exponent = m_signexp & 0x7fffffffu; uint32_t mantissa = (m_mantissa[0] << 7) | (m_mantissa[1] >> 9); - int e = (int)(m_signexp & 0x7fffffffu) - (1 << 30) + (1 << 7); + int e = (int)exponent - (1 << 30) + (1 << 7); if (e < 0) u.x = sign; @@ -65,25 +65,33 @@ real::operator float() const return u.f; } -real real::operator -() +real real::operator -() const { - m_signexp ^= 0x80000000u; - return *this; + real ret = *this; + ret.m_signexp ^= 0x80000000u; + return ret; } 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; - if (x.m_signexp << 1 == 0) - return *this; + if (m_signexp >> 31) + return -(-*this + -x); + + if (x.m_signexp >> 31) + return *this - x; - /* For now, assume both numbers are positive. */ real ret; - int e1 = (m_signexp & 0x7fffffffu) - (1 << 30) + 1; - int e2 = (x.m_signexp & 0x7fffffffu) - (1 << 30) + 1; + int e1 = m_signexp - (1 << 30) + 1; + int e2 = x.m_signexp - (1 << 30) + 1; int bigoff = (e1 - e2) / (sizeof(uint16_t) * 8); int off = e1 - e2 - bigoff * (sizeof(uint16_t) * 8); @@ -91,20 +99,20 @@ real real::operator +(real const &x) const ret.m_signexp = m_signexp; uint32_t carry = 0; - for (int i = 0; i < BIGITS; i++) + for (int i = BIGITS; i--; ) { - carry = m_mantissa[BIGITS - 1 - i]; - if (BIGITS - 1 - i - bigoff >= 0) - carry += x.m_mantissa[BIGITS - 1 - i - bigoff] >> off; - else if (BIGITS - 1 - i - bigoff == -1) + carry = m_mantissa[i]; + if (i - bigoff >= 0) + carry += x.m_mantissa[i - bigoff] >> off; + else if (i - bigoff == -1) carry += 0x0001u >> off; - if (BIGITS - 1 - i - bigoff - 1 >= 0) - carry += (x.m_mantissa[BIGITS - 1 - i - bigoff - 1] << (16 - off)) & 0xffffu; - else if (BIGITS - 1 - i - bigoff - 1 == -1) + if (i - bigoff > 0) + carry += (x.m_mantissa[i - bigoff - 1] << (16 - off)) & 0xffffu; + else if (i - bigoff == 0) carry += 0x0001u << (16 - off); - ret.m_mantissa[BIGITS - 1 - i] = carry; + ret.m_mantissa[i] = carry; carry >>= 16; } @@ -124,6 +132,27 @@ real real::operator +(real const &x) const return ret; } +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); + + if (m_signexp >> 31) + return -(-*this + x); + + if (x.m_signexp >> 31) + return (*this) + (-x); + + real ret; + + return ret; +} + real real::operator *(real const &x) const { real ret; diff --git a/src/real.h b/src/real.h index 2e2acfbb..94f27d58 100644 --- a/src/real.h +++ b/src/real.h @@ -30,8 +30,9 @@ public: real(float f); operator float() const; - real operator -(); + real operator -() const; real operator +(real const &x) const; + real operator -(real const &x) const; real operator *(real const &x) const; void print() const; diff --git a/test/unit/real.cpp b/test/unit/real.cpp index f03b5f50..3fabc757 100644 --- a/test/unit/real.cpp +++ b/test/unit/real.cpp @@ -22,7 +22,6 @@ namespace lol LOLUNIT_FIXTURE(RealTest) { -public: LOLUNIT_TEST(test_real_from_float) { float a1 = real(0.0f); @@ -53,6 +52,30 @@ public: LOLUNIT_TEST(test_real_add) { + float a1 = real(1.0f) + real(0.0f); + float a2 = real(0.0f) + real(1.0f); + float a3 = real(1.0f) + real(1.0f); + float a4 = real(-1.0f) + real(-1.0f); + float a5 = real(1.0f) + real(0.125f); + + LOLUNIT_ASSERT_EQUAL(a1, 1.0f); + LOLUNIT_ASSERT_EQUAL(a2, 1.0f); + LOLUNIT_ASSERT_EQUAL(a3, 2.0f); + LOLUNIT_ASSERT_EQUAL(a4, -2.0f); + LOLUNIT_ASSERT_EQUAL(a5, 1.125f); + } + + LOLUNIT_TEST(test_real_sub) + { +#if 0 +printf("\n"); +real k(1.25f); +k.print(); +real l(1.0f); +l.print(); +real m = k - l; +m.print(); +#endif LOLUNIT_ASSERT(true); }