Changeset 974


Ignore:
Timestamp:
Sep 22, 2011, 9:16:05 AM (9 years ago)
Author:
sam
Message:

core: implement real subtraction.

Location:
trunk
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/real.cpp

    r973 r974  
    104104    for (int i = BIGITS; i--; )
    105105    {
    106         carry = m_mantissa[i];
     106        carry += m_mantissa[i];
    107107        if (i - bigoff >= 0)
    108108            carry += x.m_mantissa[i - bigoff] >> off;
     
    154154    real ret;
    155155
     156    int e1 = m_signexp - (1 << 30) + 1;
     157    int e2 = x.m_signexp - (1 << 30) + 1;
     158
     159    int bigoff = (e1 - e2) / (sizeof(uint16_t) * 8);
     160    int off = e1 - e2 - bigoff * (sizeof(uint16_t) * 8);
     161
     162    ret.m_signexp = m_signexp;
     163
     164    int32_t carry = 0;
     165    for (int i = 0; i < bigoff; i++)
     166    {
     167        carry -= x.m_mantissa[BIGITS - i];
     168        carry = (carry & 0xffff0000u) | (carry >> 16);
     169    }
     170    carry -= x.m_mantissa[BIGITS - 1 - bigoff] & ((1 << off) - 1);
     171    carry /= (1 << off);
     172
     173    for (int i = BIGITS; i--; )
     174    {
     175        carry += m_mantissa[i];
     176        if (i - bigoff >= 0)
     177            carry -= x.m_mantissa[i - bigoff] >> off;
     178        else if (i - bigoff == -1)
     179            carry -= 0x0001u >> off;
     180
     181        if (i - bigoff > 0)
     182            carry -= (x.m_mantissa[i - bigoff - 1] << (16 - off)) & 0xffffu;
     183        else if (i - bigoff == 0)
     184            carry -= 0x0001u << (16 - off);
     185
     186        ret.m_mantissa[i] = carry;
     187        carry = (carry & 0xffff0000u) | (carry >> 16);
     188    }
     189
     190    carry += 1;
     191
     192    /* Renormalise if we underflowed the mantissa */
     193    if (carry == 0)
     194    {
     195        /* How much do we need to shift the mantissa? FIXME: this could
     196         * be computed above */
     197        off = 0;
     198        for (int i = 0; i < BIGITS; i++)
     199        {
     200            if (!ret.m_mantissa[i])
     201            {
     202                off += sizeof(uint16_t) * 8;
     203                continue;
     204            }
     205
     206            for (uint16_t tmp = ret.m_mantissa[i]; tmp < 0x8000u; tmp <<= 1)
     207                off++;
     208            break;
     209        }
     210        if (off == BIGITS * sizeof(uint16_t) * 8)
     211            ret.m_signexp &= 0x80000000u;
     212        else
     213        {
     214            off++; /* Shift one more to get rid of the leading one */
     215            ret.m_signexp -= off;
     216
     217            bigoff = off / (sizeof(uint16_t) * 8);
     218            off -= bigoff * sizeof(uint16_t) * 8;
     219
     220            for (int i = 0; i < BIGITS; i++)
     221            {
     222                uint16_t tmp = 0;
     223                if (i + bigoff < BIGITS)
     224                    tmp |= ret.m_mantissa[i + bigoff] << off;
     225                if (i + bigoff + 1 < BIGITS)
     226                    tmp |= ret.m_mantissa[i + bigoff + 1] >> (16 - off);
     227                ret.m_mantissa[i] = tmp;
     228            }
     229        }
     230    }
     231
    156232    return ret;
    157233}
  • trunk/test/unit/real.cpp

    r973 r974  
    8989    LOLUNIT_TEST(test_real_sub)
    9090    {
    91 #if 0
    92 printf("\n");
    93 real k(1.25f);
    94 k.print();
    95 real l(1.0f);
    96 l.print();
    97 real m = k - l;
    98 m.print();
    99 #endif
    100         LOLUNIT_ASSERT(true);
     91        float a1 = real(1.0f) + real(1e20f) - real(1e20f);
     92
     93        LOLUNIT_ASSERT_EQUAL(a1, 1.0f);
    10194    }
    10295
Note: See TracChangeset for help on using the changeset viewer.