diff --git a/src/real.cpp b/src/real.cpp index d012ea55..c5fa419d 100644 --- a/src/real.cpp +++ b/src/real.cpp @@ -91,6 +91,8 @@ real::operator double() const u.x |= m_mantissa[2]; u.x <<= 4; u.x |= m_mantissa[3] >> 12; + /* Rounding */ + u.x += (m_mantissa[3] >> 11) & 1; } return u.d; @@ -109,12 +111,12 @@ real real::operator +(real const &x) const return *this; /* Ensure both arguments are positive. Otherwise, switch signs, - * or replace + with -). */ + * or replace + with -. */ if (m_signexp >> 31) return -(-*this + -x); if (x.m_signexp >> 31) - return *this - x; + return *this - (-x); /* Ensure *this is the larger exponent (no need to be strictly larger, * as in subtraction). Otherwise, switch. */ @@ -137,8 +139,6 @@ real real::operator +(real const &x) const carry += m_mantissa[i]; if (i - bigoff >= 0) carry += x.m_mantissa[i - bigoff] >> off; - else if (i - bigoff == -1) - carry += 0x0001u >> off; if (i - bigoff > 0) carry += (x.m_mantissa[i - bigoff - 1] << (16 - off)) & 0xffffu; @@ -171,7 +171,7 @@ real real::operator -(real const &x) const return *this; /* Ensure both arguments are positive. Otherwise, switch signs, - * or replace - with +). */ + * or replace - with +. */ if (m_signexp >> 31) return -(-*this + x); @@ -206,8 +206,6 @@ real real::operator -(real const &x) const carry += m_mantissa[i]; if (i - bigoff >= 0) carry -= x.m_mantissa[i - bigoff] >> off; - else if (i - bigoff == -1) - carry -= 0x0001u >> off; if (i - bigoff > 0) carry -= (x.m_mantissa[i - bigoff - 1] << (16 - off)) & 0xffffu; @@ -273,20 +271,20 @@ real real::operator *(real const &x) const /* Accumulate low order product; no need to store it, we just * want the carry value */ - uint32_t carry = 0; + uint64_t carry = 0; for (int i = 0; i < BIGITS; i++) { for (int j = 0; j < i + 1; j++) - carry += m_mantissa[BIGITS - 1 - j] - * x.m_mantissa[BIGITS - 1 + j - i]; + carry += (uint32_t)m_mantissa[BIGITS - 1 - j] + * (uint32_t)x.m_mantissa[BIGITS - 1 + j - i]; carry >>= 16; } for (int i = 0; i < BIGITS; i++) { for (int j = i + 1; j < BIGITS; j++) - carry += m_mantissa[BIGITS - 1 - j] - * x.m_mantissa[j - 1 - i]; + carry += (uint32_t)m_mantissa[BIGITS - 1 - j] + * (uint32_t)x.m_mantissa[j - 1 - i]; carry += m_mantissa[BIGITS - 1 - i]; carry += x.m_mantissa[BIGITS - 1 - i]; diff --git a/test/unit/real.cpp b/test/unit/real.cpp index 84cc6f0a..b6db9495 100644 --- a/test/unit/real.cpp +++ b/test/unit/real.cpp @@ -97,12 +97,19 @@ LOLUNIT_FIXTURE(RealTest) float a3 = real(1.0f) + real(1.0f); float a4 = real(-1.0f) + real(-1.0f); float a5 = real(1.0f) + real(0.125f); + double a6 = real(3.13609818956293918) + + real(0.00005972154828114); + float a7 = real(1.0f) + real(-0.125f); + double a8 = real(0.10000000002) + real(-2.0e-11); 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_ASSERT_DOUBLES_EQUAL(a6, 3.1361579, 0.000001); + LOLUNIT_ASSERT_EQUAL(a7, 0.875f); + LOLUNIT_ASSERT_DOUBLES_EQUAL(a8, 0.1, 1.0e-13); } LOLUNIT_TEST(RealSubtraction) @@ -139,11 +146,13 @@ LOLUNIT_FIXTURE(RealTest) float m2 = a2 / a1; float m3 = a1 / a2; float m4 = a2 / a2; + float m5 = a1 / -a2; LOLUNIT_ASSERT_EQUAL(m1, 1.0f); LOLUNIT_ASSERT_EQUAL(m2, 2.0f); LOLUNIT_ASSERT_EQUAL(m3, 0.5f); LOLUNIT_ASSERT_EQUAL(m4, 1.0f); + LOLUNIT_ASSERT_EQUAL(m5, -0.5f); } };