Browse Source

core: handle zero, negative zero and infinite in the real constructor,

and add a test suite check for unary minus.
legacy
Sam Hocevar sam 13 years ago
parent
commit
884978c71b
2 changed files with 50 additions and 12 deletions
  1. +27
    -6
      src/real.cpp
  2. +23
    -6
      test/unit/real.cpp

+ 27
- 6
src/real.cpp View File

@@ -27,9 +27,19 @@ real::real(float f)
union { float f; uint32_t x; } u = { f };

uint32_t sign = u.x & 0x80000000u;
int e = ((u.x >> 23) & 0xff) + (1 << 30) - (1 << 7);
uint32_t exponent = (u.x >> 23) & 0xff;

switch (exponent)
{
case 0x00:
case 0xff:
m_signexp = sign | exponent;
break;
default:
m_signexp = sign | (exponent + (1 << 30) - (1 << 7));
break;
}

m_signexp = sign | e;
m_mantissa[0] = u.x >> 7;
m_mantissa[1] = u.x << 9;
memset(m_mantissa + 2, 0, sizeof(m_mantissa) - sizeof(m_mantissa[0]));
@@ -39,10 +49,18 @@ real::operator float() const
{
union { float f; uint32_t x; } u;

u.x = m_mantissa[0] << 7;
u.x |= m_mantissa[1] >> 9;
u.x |= ((m_signexp & 0x7fffffffu) - (1 << 30) + (1 << 7)) << 23;
u.x |= m_signexp & 0x80000000u;
uint32_t sign = m_signexp & 0x80000000u;
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);

if (e < 0)
u.x = sign;
else if (e >= 0xff)
u.x = sign | (0xff << 23);
else
u.x = sign | (e << 23) | mantissa;

return u.f;
}
@@ -58,6 +76,9 @@ real real::operator +(real const &x) const
if ((m_signexp << 1) < (x.m_signexp << 1))
return x + *this;

if (x.m_signexp << 1 == 0)
return *this;

/* For now, assume both numbers are positive. */
real ret;



+ 23
- 6
test/unit/real.cpp View File

@@ -25,13 +25,30 @@ LOLUNIT_FIXTURE(RealTest)
public:
LOLUNIT_TEST(test_real_from_float)
{
float x = real(0.0f);
float y = real(1.0f);
float z = real(1.5f);
float a1 = real(0.0f);
float a2 = real(-0.0f);
float a3 = real(1.0f);
float a4 = real(-1.0f);
float a5 = real(1.5f);

LOLUNIT_ASSERT_EQUAL(x, 0.0f);
LOLUNIT_ASSERT_EQUAL(y, 1.0f);
LOLUNIT_ASSERT_EQUAL(z, 1.5f);
LOLUNIT_ASSERT_EQUAL(a1, 0.0f);
LOLUNIT_ASSERT_EQUAL(a2, -0.0f);
LOLUNIT_ASSERT_EQUAL(a3, 1.0f);
LOLUNIT_ASSERT_EQUAL(a4, -1.0f);
LOLUNIT_ASSERT_EQUAL(a5, 1.5f);
}

LOLUNIT_TEST(test_real_neg)
{
float a1 = - real(1.0f);
float a2 = - real(-1.0f);
float a3 = - real(0.0f);
float a4 = - real(-0.0f);

LOLUNIT_ASSERT_EQUAL(a1, -1.0f);
LOLUNIT_ASSERT_EQUAL(a2, 1.0f);
LOLUNIT_ASSERT_EQUAL(a3, -0.0f);
LOLUNIT_ASSERT_EQUAL(a4, 0.0f);
}

LOLUNIT_TEST(test_real_add)


Loading…
Cancel
Save