Changeset 976


Ignore:
Timestamp:
Sep 22, 2011, 6:16:51 PM (11 years ago)
Author:
sam
Message:

core: allow to cast reals to doubles in addition to floats.

Location:
trunk
Files:
3 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/real.cpp

    r975 r976  
    2525real::real(float f)
    2626{
    27     union { float f; uint32_t x; } u = { f };
    28 
    29     uint32_t sign = u.x & 0x80000000u;
    30     uint32_t exponent = (u.x >> 23) & 0xff;
     27    new(this) real((double)f);
     28}
     29
     30real::real(double d)
     31{
     32    union { double d; uint64_t x; } u = { d };
     33
     34    uint32_t sign = (u.x >> 63) << 31;
     35    uint32_t exponent = (u.x << 1) >> 53;
    3136
    3237    switch (exponent)
    3338    {
    3439    case 0x00:
    35     case 0xff:
    36         m_signexp = sign | exponent;
     40        m_signexp = sign;
     41        break;
     42    case 0x7ff:
     43        m_signexp = sign | 0x7fffffffu;
    3744        break;
    3845    default:
    39         m_signexp = sign | (exponent + (1 << 30) - (1 << 7));
     46        m_signexp = sign | (exponent + (1 << 30) - (1 << 10));
    4047        break;
    4148    }
    4249
    43     m_mantissa[0] = u.x >> 7;
    44     m_mantissa[1] = u.x << 9;
    45     memset(m_mantissa + 2, 0, sizeof(m_mantissa) - sizeof(m_mantissa[0]));
     50    m_mantissa[0] = u.x >> 36;
     51    m_mantissa[1] = u.x >> 20;
     52    m_mantissa[2] = u.x >> 4;
     53    m_mantissa[3] = u.x << 12;
     54    memset(m_mantissa + 4, 0, sizeof(m_mantissa) - 4 * sizeof(m_mantissa[0]));
    4655}
    4756
    4857real::operator float() const
    4958{
    50     union { float f; uint32_t x; } u;
    51 
    52     uint32_t sign = m_signexp & 0x80000000u;
    53     uint32_t exponent = m_signexp & 0x7fffffffu;
    54     uint32_t mantissa = (m_mantissa[0] << 7) | (m_mantissa[1] >> 9);
    55 
    56     int e = (int)exponent - (1 << 30) + (1 << 7);
     59    return (float)(double)(*this);
     60}
     61
     62real::operator double() const
     63{
     64    union { double d; uint64_t x; } u;
     65
     66    /* Get sign */
     67    u.x = m_signexp >> 31;
     68    u.x <<= 11;
     69
     70    /* Compute new exponent */
     71    uint32_t exponent = (m_signexp << 1) >> 1;
     72    int e = (int)exponent - (1 << 30) + (1 << 10);
    5773
    5874    if (e < 0)
    59         u.x = sign;
    60     else if (e >= 0xff)
    61         u.x = sign | (0xff << 23);
     75        u.x <<= 52;
     76    else if (e >= 0x7ff)
     77    {
     78        u.x |= 0x7ff;
     79        u.x <<= 52;
     80    }
    6281    else
    63         u.x = sign | (e << 23) | mantissa;
    64 
    65     return u.f;
     82    {
     83        u.x |= e;
     84
     85        /* Store mantissa if necessary */
     86        u.x <<= 16;
     87        u.x |= m_mantissa[0];
     88        u.x <<= 16;
     89        u.x |= m_mantissa[1];
     90        u.x <<= 16;
     91        u.x |= m_mantissa[2];
     92        u.x <<= 4;
     93        u.x |= m_mantissa[3] >> 12;
     94    }
     95
     96    return u.d;
    6697}
    6798
  • trunk/src/real.h

    r975 r976  
    2929    inline real() { }
    3030    real(float f);
     31    real(double f);
    3132
    3233    operator float() const;
     34    operator double() const;
    3335
    3436    real operator -() const;
  • trunk/test/unit/real.cpp

    r975 r976  
    3030        float a4 = real(-1.0f);
    3131        float a5 = real(1.5f);
     32        float a6 = real(12345678.0f);
    3233
    3334        LOLUNIT_ASSERT_EQUAL(a1, 0.0f);
     
    3637        LOLUNIT_ASSERT_EQUAL(a4, -1.0f);
    3738        LOLUNIT_ASSERT_EQUAL(a5, 1.5f);
     39        LOLUNIT_ASSERT_EQUAL(a6, 12345678.0f);
     40    }
     41
     42    LOLUNIT_TEST(test_real_from_double)
     43    {
     44        double a1 = real(0.0);
     45        double a2 = real(-0.0);
     46        double a3 = real(1.0);
     47        double a4 = real(-1.0);
     48        double a5 = real(1.5);
     49        double a6 = real(1234567876543210.0);
     50
     51        LOLUNIT_ASSERT_DOUBLES_EQUAL(a1, 0.0, 0.0);
     52        LOLUNIT_ASSERT_DOUBLES_EQUAL(a2, -0.0, 0.0);
     53        LOLUNIT_ASSERT_DOUBLES_EQUAL(a3, 1.0, 0.0);
     54        LOLUNIT_ASSERT_DOUBLES_EQUAL(a4, -1.0, 0.0);
     55        LOLUNIT_ASSERT_DOUBLES_EQUAL(a5, 1.5, 0.0);
     56        LOLUNIT_ASSERT_DOUBLES_EQUAL(a6, 1234567876543210.0, 0.0);
    3857    }
    3958
Note: See TracChangeset for help on using the changeset viewer.