Changeset 969


Ignore:
Timestamp:
Sep 21, 2011, 7:10:21 PM (10 years ago)
Author:
sam
Message:

core: switch real mantissa to uint16_t instead of uint32_t to ease the
multiplication.

Location:
trunk
Files:
3 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/real.cpp

    r965 r969  
    1414
    1515#include <cstring>
     16#include <cstdio>
    1617
    1718#include "core.h"
     
    2223{
    2324
    24 template<> real4k::Real(float f)
     25real::real(float f)
    2526{
    2627    union { float f; uint32_t x; } u = { f };
    2728
    2829    uint32_t sign = u.x & 0x80000000u;
    29     int e = ((u.x >> 23) & 0xff) + (1 << 30) - (1 << 10);
     30    int e = ((u.x >> 23) & 0xff) + (1 << 30) - (1 << 7);
    3031
    3132    m_signexp = sign | e;
    32     m_mantissa[0] = u.x << 17;
    33     memset(m_mantissa + 1, 0, sizeof(m_mantissa) - sizeof(m_mantissa[0]));
     33    m_mantissa[0] = u.x >> 7;
     34    m_mantissa[1] = u.x << 9;
     35    memset(m_mantissa + 2, 0, sizeof(m_mantissa) - sizeof(m_mantissa[0]));
    3436}
    3537
    36 template<> real4k::operator float() const
     38real::operator float() const
    3739{
    3840    union { float f; uint32_t x; } u;
    3941
    40     u.x = m_mantissa[0] >> 17;
    41     u.x |= ((m_signexp & 0x7fffffffu) - (1 << 30) + (1 << 10)) << 23;
     42    u.x = m_mantissa[0] << 7;
     43    u.x |= m_mantissa[1] >> 9;
     44    u.x |= ((m_signexp & 0x7fffffffu) - (1 << 30) + (1 << 7)) << 23;
    4245    u.x |= m_signexp & 0x80000000u;
    4346
     
    4548}
    4649
     50real real::operator *(real const &x) const
     51{
     52    real ret;
     53
     54    ret.m_signexp = (m_signexp ^ x.m_signexp) & 0x80000000u;
     55    int e = (m_signexp & 0x7fffffffu) - (1 << 30) + 1
     56          + (x.m_signexp & 0x7fffffffu) - (1 << 30) + 1;
     57
     58    /* Accumulate low order product; no need to store it, we just
     59     * want the carry value */
     60    uint32_t carry = 0;
     61    for (int i = 0; i < BIGITS; i++)
     62    {
     63        for (int j = 0; j < i + 1; j++)
     64            carry += m_mantissa[BIGITS - 1 - j]
     65                   * x.m_mantissa[BIGITS - 1 + j - i];
     66        carry >>= 16;
     67    }
     68
     69    for (int i = 0; i < BIGITS; i++)
     70    {
     71        for (int j = i + 1; j < BIGITS; j++)
     72            carry += m_mantissa[BIGITS - 1 - j]
     73                   * x.m_mantissa[j - 1 - i];
     74
     75        carry += m_mantissa[BIGITS - 1 - i];
     76        carry += x.m_mantissa[BIGITS - 1 - i];
     77        ret.m_mantissa[BIGITS - 1 - i] = carry & 0xffffu;
     78        carry >>= 16;
     79    }
     80
     81    /* Renormalise in case we overflowed the mantissa */
     82    if (carry)
     83    {
     84        carry--;
     85        for (int i = 0; i < BIGITS; i++)
     86        {
     87            uint16_t tmp = ret.m_mantissa[i];
     88            ret.m_mantissa[i] = (carry << 15) | (tmp >> 1);
     89            carry = tmp & 0x0001u;
     90        }
     91        e++;
     92    }
     93
     94    ret.m_signexp |= e + (1 << 30) - 1;
     95
     96    return ret;
     97}
     98
     99void real::print() const
     100{
     101    printf("%x  %08x  ", m_signexp >> 31, (m_signexp << 1) >> 1);
     102    for (int i = 0; i < BIGITS; i++)
     103        printf("%04x ", m_mantissa[i]);
     104    printf("\n");
     105}
     106
    47107} /* namespace lol */
    48108
  • trunk/src/real.h

    r965 r969  
    2222{
    2323
    24 template<int NBITS> class Real
     24class real
    2525{
     26    static int const BIGITS = 10;
     27
    2628public:
    27     inline Real<NBITS>() {}
    28     Real<NBITS>(float f);
     29    inline real() { }
     30    real(float f);
    2931
    3032    operator float() const;
     33    real operator *(real const &x) const;
     34
     35    void print() const;
    3136
    3237private:
     38    uint32_t m_size;
    3339    uint32_t m_signexp;
    34     uint32_t m_mantissa[(NBITS + 31) / 32];
     40    uint16_t m_mantissa[BIGITS];
    3541};
    36 
    37 typedef Real<4096> real4k;
    3842
    3943} /* namespace lol */
  • trunk/test/unit/real.cpp

    r967 r969  
    2626    LOLUNIT_TEST(test_real_from_float)
    2727    {
    28         float x = real4k(0.0f);
    29         float y = real4k(1.0f);
     28        float x = real(0.0f);
     29        float y = real(1.0f);
     30        float z = real(1.5f);
    3031
    3132        LOLUNIT_ASSERT_EQUAL(x, 0.0f);
    3233        LOLUNIT_ASSERT_EQUAL(y, 1.0f);
     34        LOLUNIT_ASSERT_EQUAL(z, 1.5f);
     35    }
     36
     37    LOLUNIT_TEST(test_real_mul)
     38    {
     39        real x(1.25f);
     40        real y(1.5f);
     41        real z(1.99999f);
     42        real w(-1.5f);
     43
     44        float m1 = x * x;
     45        float m2 = y * y;
     46        float m3 = z * z;
     47        float m4 = w * w;
     48
     49        LOLUNIT_ASSERT_EQUAL(m1, 1.25f * 1.25f);
     50        LOLUNIT_ASSERT_EQUAL(m2, 1.5f * 1.5f);
     51        LOLUNIT_ASSERT_EQUAL(m3, 1.99999f * 1.99999f);
     52        LOLUNIT_ASSERT_EQUAL(m4, -1.5f * -1.5f);
    3353    }
    3454};
Note: See TracChangeset for help on using the changeset viewer.