Changeset 1002


Ignore:
Timestamp:
Oct 3, 2011, 1:36:28 AM (9 years ago)
Author:
sam
Message:

core: implement floor() and ceil() for real numbers.

Location:
trunk
Files:
3 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/real.cpp

    r1001 r1002  
    638638    x1.m_signexp += e0;
    639639    return x1;
     640}
     641
     642real floor(real const &x)
     643{
     644    /* Strategy for floor(x):
     645     *  - if negative, return -ceil(-x)
     646     *  - if zero or negative zero, return x
     647     *  - if less than one, return zero
     648     *  - otherwise, if e is the exponent, clear all bits except the
     649     *    first e. */
     650    if (x < -real::R_0)
     651        return -ceil(-x);
     652    if (!x)
     653        return x;
     654    if (x < real::R_1)
     655        return real::R_0;
     656
     657    real ret = x;
     658    int exponent = x.m_signexp - (1 << 30) + 1;
     659
     660    for (int i = 0; i < real::BIGITS; i++)
     661    {
     662        if (exponent <= 0)
     663            ret.m_mantissa[i] = 0;
     664        else if (exponent < 8 * (int)sizeof(uint16_t))
     665            ret.m_mantissa[i] &= ~((1 << (16 - exponent)) - 1);
     666
     667        exponent -= 8 * sizeof(uint16_t);
     668    }
     669
     670    return ret;
     671}
     672
     673real ceil(real const &x)
     674{
     675    /* Strategy for ceil(x):
     676     *  - if negative, return -floor(-x)
     677     *  - if x == floor(x), return x
     678     *  - otherwise, return floor(x) + 1 */
     679    if (x < -real::R_0)
     680        return -floor(-x);
     681    real ret = floor(x);
     682    if (x == ret)
     683        return ret;
     684    else
     685        return ret + real::R_1;
    640686}
    641687
  • trunk/src/real.h

    r1001 r1002  
    7070    friend real exp(real const &x);
    7171
     72    friend real floor(real const &x);
     73    friend real ceil(real const &x);
     74
    7275    friend real sin(real const &x);
    7376    friend real cos(real const &x);
  • trunk/test/unit/real.cpp

    r1001 r1002  
    240240    LOLUNIT_TEST(AsinAcos)
    241241    {
    242         double tests[14] =
     242        double tests[] =
    243243        {
    244244            -1024.0, -1023.0, -513.0, -512.0, -511.0, -1.0, -0.0,
     
    246246        };
    247247
    248         for (int n = 0; n < 14; n++)
     248        for (unsigned int n = 0; n < sizeof(tests) / sizeof(*tests); n++)
    249249        {
    250250            double a = tests[n] / 1024;
     
    257257        }
    258258    }
     259
     260    LOLUNIT_TEST(FloorCeil)
     261    {
     262        double tests[] =
     263        {
     264            -2.0,  -2.0, -2.0,
     265            -1.5,  -2.0, -1.0,
     266            -1.0,  -1.0, -1.0,
     267            -0.0,  -0.0, -0.0,
     268             0.0,   0.0,  0.0,
     269             0.25,  0.0,  1.0,
     270             0.375, 0.0,  1.0,
     271             0.5,   0.0,  1.0,
     272             1.0,   1.0,  1.0,
     273             1.5,   1.0,  2.0,
     274             2.0,   2.0,  2.0,
     275             2.5,   2.0,  3.0,
     276             3.0,   3.0,  3.0,
     277            8192.0,     8192.0, 8192.0,
     278            8192.03125, 8192.0, 8193.0,
     279            8192.5,     8192.0, 8193.0,
     280            8193.0,     8193.0, 8193.0,
     281            549755813888.0,     549755813888.0, 549755813888.0,
     282            549755813888.03125, 549755813888.0, 549755813889.0,
     283            549755813888.5,     549755813888.0, 549755813889.0,
     284            549755813889.0,     549755813889.0, 549755813889.0,
     285        };
     286
     287        for (unsigned int n = 0; n < sizeof(tests) / sizeof(*tests); n += 3)
     288        {
     289            double a0 = floor((real)tests[n]);
     290            double b0 = tests[n + 1];
     291            double a1 = ceil((real)tests[n]);
     292            double b1 = tests[n + 2];
     293
     294            LOLUNIT_ASSERT_EQUAL(b0, a0);
     295            LOLUNIT_ASSERT_EQUAL(b1, a1);
     296        }
     297    }
    259298};
    260299
Note: See TracChangeset for help on using the changeset viewer.