Browse Source

core: fix real unary minus and handle negative numbers in additions.

legacy
Sam Hocevar sam 13 years ago
parent
commit
48f00deff9
3 changed files with 73 additions and 20 deletions
  1. +47
    -18
      src/real.cpp
  2. +2
    -1
      src/real.h
  3. +24
    -1
      test/unit/real.cpp

+ 47
- 18
src/real.cpp View File

@@ -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;


+ 2
- 1
src/real.h View File

@@ -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;


+ 24
- 1
test/unit/real.cpp View File

@@ -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);
}



Loading…
Cancel
Save